homeport/dyff for concise YAML and JSON comparisons
/ˈdʏf/ - diff tool for YAML files, and sometimes JSON
At a glance
- What is it?
- dyff is a Go command-line tool for comparing structured YAML and JSON while identifying changes by document path. It also converts between formats, preserves map key order, and can plug into kubectl and Git workflows.
- Who is it for?
- dyff is a good fit for engineers who routinely inspect YAML configuration changes and need compact, path-based reports rather than raw textual diffs. It is less suitable for workflows that require line-oriented patch output or where key order must be treated as insignificant.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 9 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why dyff targets structured configuration review
dyff addresses a specific weakness in ordinary text comparison for configuration files. A small YAML value change can appear in a conventional line diff beside indentation, context, or unrelated formatting, while a reordered or transformed document can produce a report that is difficult to scan. dyff instead describes the transition from a `from` input to a target `to` input and attempts to keep the output compact.
The tool is aimed at engineers and operators working with YAML configuration, especially BOSH deployment manifests, Kubernetes resources, and related automation. The README also describes JSON support, although its own description qualifies that support as occasional rather than making it the sole focus.
Each reported change receives a location in the document. dyff supports Spruce dot-style paths such as `some.path.in.the.file` and go-patch paths such as `/some/name=path/in/the/id=file`. This is a material difference from tools that print only changed lines: the recipient can identify the changed YAML value by its structural address instead of reconstructing it from surrounding lines.
Inputs may be local filesystem paths, remote URIs, or standard input through `-`. That range makes dyff usable both for two saved manifest versions and for a pipeline in which a command emits JSON or YAML on standard output.
How dyff represents and compares document changes
The repository layout separates the command entry point under `cmd/dyff`, command behavior under `internal/cmd`, and the public package under `pkg/dyff`. Its dependencies indicate a Cobra-based CLI and YAML processing through `go.yaml.in/yaml/v3`, while `github.com/gonvenience/ytbx` appears in the module as the YAML toolbox layer. These details support the repository's apparent split between CLI presentation and document comparison logic, although the README does not publish an internal algorithm or complexity analysis.
Two deliberate choices are documented. First, the tool preserves every order of keys in hashes during processing and output. This matters for conversion and restructuring because converting a map through an order-insensitive representation could otherwise produce a large amount of avoidable rearrangement. Second, the `between` command follows the same directional idea as standard `diff`: the first input is the source and the second is the target.
The output is designed to be compact and path-addressed. Colors and indentation guides are enabled by default for terminal display, based roughly on Atom's schema, but neat output is disabled when output is redirected. The `--plain` flag can disable it explicitly. That behavior makes interactive inspection different from redirected output, which matters when integrating dyff into scripts or reviewing generated files.
The `yaml` and `json` subcommands convert content while automatically detecting the input format. The input can still be JSON when `dyff yaml` is requested, or YAML when `dyff json` is requested. Order preservation is particularly relevant here because it gives the conversion and restructuring commands defined output behavior.
Installing dyff and running the first comparison
The quickest documented source installation uses Go and places the latest code-based version through Go's standard installer. The README says that this is not its recommended installation path because it tracks the latest available code base rather than selecting a stable release.
go install github.com/homeport/dyff/cmd/dyff@latestFor users who prefer a packaged release, the Homebrew tap supplies prebuilt binaries for macOS and GNU/Linux.
brew install homeport/tap/dyffAfter choosing an install channel, a first comparison can use the two `cf-deployment` versions named in the README. The first URL is the `from` input and the second is the target.
dyff between \
https://raw.githubusercontent.com/cloudfoundry/cf-deployment/v1.10.0/cf-deployment.yml \
https://raw.githubusercontent.com/cloudfoundry/cf-deployment/v1.20.0/cf-deployment.ymlThe expected result is a compact report whose changes are referenced by Spruce or go-patch paths. The README illustrates this use case but does not provide a fixed console transcript for those specific URLs, so the exact changed paths depend on the manifests at those revisions.
Local files use the same command structure. Standard input can be supplied with `-` when an upstream tool produces the document. This makes dyff applicable to generated configuration without requiring a temporary file, provided the other input is also available in a form accepted by the command.
Using dyff with kubectl, Git, and streamed JSON
dyff has integrations for two workflows that commonly produce configuration differences. For `kubectl diff` versions at or above `v1.20.0`, the README configures `KUBECTL_EXTERNAL_DIFF` so that `dyff between` supplies the Kubernetes exit behavior expected by kubectl.
export KUBECTL_EXTERNAL_DIFF="dyff between --omit-header --set-exit-code"After exporting that variable, the documented invocation uses kubectl's normal diff argument syntax.
kubectl diff [...]The `--set-exit-code` requirement is significant. According to the README, exit code `0` means no differences, while `1` means differences were detected. Other exit codes are treated as program problems. Consumers should not treat every nonzero result as an ordinary configuration difference.
Older kubectl releases did not split the environment variable into fields, so dyff cannot pass its arguments in the same way. The documented workaround is a helper shell script, not a newer dyff flag.
Git can also invoke dyff for YAML files. The following configuration creates the shell function and records the file pattern in the repository's attributes.
git config --local diff.dyff.command 'dyff_between() { dyff --color on between --omit-header "$2" "$5"; }; dyff_between'
echo '*.yml diff=dyff' >> .gitattributesThe README then uses Git's external-diff commands to inspect history.
git log --ext-diff -u
git show --ext-diff HEADFor conversion, `dyff yaml -` can read a JSON stream, while `dyff yaml --restructure -` can rewrite the order of map keys. In-place restructuring is also documented for a named YAML file.
dyff yaml --restructure --in-place somefile.ymlWhere dyff is a poor substitute for text diff tools
dyff is the wrong tool when the required deliverable is a conventional line-oriented patch. The README focuses on path-addressed, compact change reports and format-aware conversion. It does not document machine-readable unified diff output or a patch application mode. A workflow that expects unified-diff hunks, exact line movement, or an existing patch consumer should verify that requirement before standardizing on dyff.
It is also a questionable choice for plain-text files. Its input model is structured YAML, with JSON support described as occasional. Although standard input and remote files are convenient transport mechanisms, that does not make arbitrary text a documented use case.
Key-order handling presents another design decision rather than a universal advantage. dyff deliberately preserves map key order, including in conversion and restructuring commands. This is useful when order carries meaning for a human or a downstream representation, but preserving order can make the result less minimal if the receiving workflow considers all map order irrelevant.
The kubectl integration also carries version constraints. Direct arguments through `KUBECTL_EXTERNAL_DIFF` require kubectl version `v1.20.0` or later. Older releases need a helper script because they do not split the environment variable into a field and command arguments. That is a modest constraint for new deployments, but it matters in long-lived environments pinned to older kubectl versions.
Finally, the newest source installation is not pinned. The README explicitly advises against the `go install ...@latest` route as its preferred setup method. Teams that require reproducible binaries should select a release through Homebrew, package management, or a downloaded GitHub release instead.
Comparing dyff with format conversion and general-purpose diff utilities
A real alternative approach is to use a general-purpose text diff utility for YAML. That approach compares serialized lines without requiring understanding of map keys, sequence entries, or document paths. It can be a better fit when reviewers need a unified patch, when a downstream tool consumes standard diff syntax, or when the input is plain text rather than structured YAML.
dyff takes a different route. It parses structured input, reports changes from a source document to a target document, and labels changes with Spruce or go-patch locations. It also offers format conversion and explicit map-key restructuring. The README does not document a patch-generation mode, so this is primarily a comparison and inspection tool rather than a replacement for patch-producing diff workflows.
Another alternative is to use a YAML-aware editor or platform-specific configuration management system that already renders live and desired resource differences. Such a system can reduce command assembly for that platform, but it is not the approach documented here. dyff is platform-neutral at the core CLI level and accepts local paths, remote URIs, and streams, while its specific kubectl example exists to connect it to Kubernetes workflows.
The practical choice comes down to output contract. Use text diff when line-oriented patches are mandatory. Use dyff when reviewers benefit from concise structural paths, preserve map-key order, or need YAML and JSON conversion alongside comparison. For Kubernetes specifically, verify that the selected kubectl version can pass external-diff arguments and that the exit-code contract is preserved.
Release cadence, Go dependencies, and MIT licensing
The repository is not archived, and its last push was on 2026-10-14. The listed releases include v1.12.0 on 2026-04-26, v1.11.4 on 2026-04-25, and v1.11.3 on 2026-03-17. Those dates indicate recent repository activity, but the release list does not establish a fixed support schedule or a long-term compatibility policy.
The module declares `go 1.26.0` in `go.mod`. This is separate from the README's installation statement that source installation with `go install` starts with Go 1.17. For reproducible builds, the declared module requirement is the more specific repository fact to check against the intended build environment.
The source installation command requests `@latest`, so it does not pin a release. That reduces setup effort but can change when Go resolves a newer revision. Package-manager and downloaded-release installs can provide a separately managed version, although the README does not state the exact format of every packaging channel or the duration of upgrade support.
dyff is distributed under the MIT License. The repository includes the MIT permission and warranty disclaimer in its license text. For organizational use, that generally means the source code may be used, modified, and redistributed under the license's notice and disclaimer conditions. This review does not provide legal advice, and downstream projects should retain the required notice when distributing copies or substantial portions.
Editorial conclusion
dyff is a good fit for engineers who routinely inspect YAML configuration changes and need compact, path-based reports rather than raw textual diffs. It is less suitable for workflows that require line-oriented patch output or where key order must be treated as insignificant. Before adoption, verify the selected install channel and check whether downstream scripts depend on dyff's documented exit codes, especially the Kubernetes integration with `between --omit-header --set-exit-code`.
Frequently asked questions
How do I install dyff from source?
The README documents `go install github.com/homeport/dyff/cmd/dyff@latest`, but it says this is not the recommended route because it installs the latest available code base rather than selecting a stable release.
Can dyff compare local YAML files and remote files?
Yes. Inputs can be local filesystem paths, remote URIs, or standard input through `-`, and `dyff between` treats the first input as the source and the second as the target.
Does dyff work with kubectl diff?
Yes, for kubectl version `v1.20.0` or later according to the README. The documented configuration sets `KUBECTL_EXTERNAL_DIFF` to `dyff between --omit-header --set-exit-code`.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/homeport-dyff)Was this useful?