YAML for Go, with the control your application needs.
Release Status: v4.0.0 is not released yet. It is intended to be released in October 2026. This README describes the v4 API and tools being prepared for that release.
Read YAML into Go values, work with nodes and comments, and write YAML with
explicit control over formatting and behavior.
Use the same processing pipeline from Go or from the go-yaml command.
Maintained by the YAML organization.
Get started · CLI · Options · Plugins · Documentation · Migration
v2 and v3 remain stable. Their APIs are frozen, and their branches receive security fixes only. New features and routine bug fixes are developed in v4.
| Version | Import path | Status |
|---|---|---|
| v2 | go.yaml.in/yaml/v2 |
Stable, frozen API; security fixes only |
| v3 | go.yaml.in/yaml/v3 |
Stable, frozen API; security fixes only |
| v4 | go.yaml.in/yaml/v4 |
Active development |
v4 is designed to be highly compatible with v3.
The classic Unmarshal, Marshal, NewDecoder, and NewEncoder entry points
remain available.
The new Load and Dump APIs add options, plugins, and clearer configuration.
Version presets restore v3 defaults, with individual options for finer control.
See the migration guide for formatting, error
handling, and custom unmarshaler details before upgrading.
go get go.yaml.in/yaml/v4Load into structs, maps, slices, or your own types.
Export struct fields and use yaml tags to control their names:
package main
import (
"fmt"
"log"
"go.yaml.in/yaml/v4"
)
type Config struct {
Name string `yaml:"name"`
Port int `yaml:"port"`
}
func main() {
input := []byte("name: api\nport: 8080\n")
var config Config
if err := yaml.Load(input, &config, yaml.WithKnownFields()); err != nil {
log.Fatal(err)
}
output, err := yaml.Dump(config, yaml.WithIndent(4))
if err != nil {
log.Fatal(err)
}
fmt.Print(string(output))
}Output:
name: api
port: 8080Use NewLoader and NewDumper for streams and yaml.Node when you need
access to tags, styles, anchors, comments, or source positions.
Both constructors return an error; check it before using the stream.
See the runnable examples and
API reference.
See what YAML is doing at every stage. The CLI exposes the library's scanner, parser, node tree, and output formats. Use it to inspect configuration, explore options, compare behavior, and make bug reports reproducible.
go install go.yaml.in/yaml/v4/cmd/go-yaml@latestUse this config.yaml:
# Service configuration
service:
name: api
port: 8080Try the same commands with your own file:
go-yaml -J config.yaml
go-yaml -n config.yaml
go-yaml -Y -o indent=4 config.yaml
go-yaml -t config.yaml | go-yaml -e | go-yaml -N | go-yaml -Y| Output | Flags | What you can inspect |
|---|---|---|
| YAML | -y / -Y |
Ordinary encoding / node-aware styles and comments |
| JSON | -j / -J |
Compact / pretty-printed JSON |
| Tokens | -t / -T |
Scanner tokens / tokens with source positions |
| Events | -e / -E |
Parser events / events with source positions |
| Nodes | -n / -N |
Compact tree / tags and styles included |
Select an output mode and pass a file, or pipe input on standard input.
Put flags before the file name.
Token, event, and node output can be piped into later stages, as shown above.
Use -f yaml to force YAML input when a document resembles an intermediate
stage's representation.
Backward stage conversions are rejected.
The CLI also supports:
- Options:
-o indent=4, repeated-oflags, and presets such as-o v3. Rungo-yaml -o helpto discover available settings. - Configuration:
-C options.yamlloads a reusable options file. Command-line-osettings override its individual non-plugin options. - Plugins:
--pluginselects implementations linked into the executable. Build optional implementations withmake cli PLUGIN=..., or usemake cli CONFIG=options.yamlto embed a configuration and its plugins. - Layout:
-lselects block layout for stage representations. - Classic APIs:
--unmarshal,--decode,--marshal, and--encodehelp compare classic library paths with the default Load/Dump pipeline.
Node-aware YAML output retains supported styles and comments; it does not promise byte-for-byte formatting preservation. See the CLI guide for pipelines, plugin builds, configuration, and processing-mode restrictions. The demo source and recording instructions are included.
Choose strict loading, indentation, sequence layout, line width, document markers, Unicode handling, and more without wrapping or forking the library. Options work with package functions, streaming loaders and dumpers, and node methods.
err := yaml.Load(input, &config,
yaml.WithKnownFields(),
yaml.WithUniqueKeys(),
)yaml.Load rejects additional documents by default.
Use yaml.NewLoader to process a stream one document at a time.
Start from a version preset and override only what you need. Options are applied in order:
output, err := yaml.Dump(config,
yaml.WithV3Defaults(),
yaml.WithIndent(2),
)Load and Dump use v4 defaults: two-space indentation and compact sequences.
The classic APIs retain their compatibility settings.
To match Marshal formatting when switching to Dump, use
WithV3Defaults() followed by WithLineWidth(-1).
Presets select defaults; they do not reverse every v4 bug fix or API change.
You can also share configuration between Go code and the CLI:
indent: 4
compact-seq-indent: false
line-width: 100In Go, parse that YAML with yaml.OptsYAML, check the returned error, and pass
the resulting option to Load, Dump, or a stream constructor.
On the command line, use go-yaml -Y -C options.yaml config.yaml.
See the options guide for the full reference and presets.
go-yaml's plugin APIs let you adapt YAML processing to your application. Use the supplied implementations or implement the public interfaces in your own Go package.
These are the current plugin APIs, with many more to come:
| Plugin API | Purpose | Supplied implementations |
|---|---|---|
loader-limits |
Control nesting and alias limits | Core loader-limits plugin |
error-format |
Choose how structured errors are presented | Core v3 and v4 formatters |
yaml-parser |
Replace the parser behind the node pipeline | Built-in Go parser; optional reference parser module |
tab-indent |
Enable and configure tab-indented input | Core opt-in tab-indent plugin |
For example, set a nesting-depth limit directly in Go:
import (
"go.yaml.in/yaml/v4"
"go.yaml.in/yaml/v4/plugin/loaderlimits"
)
// Inside your loading function:
err := yaml.Load(input, &config,
yaml.WithPlugin(loaderlimits.New(loaderlimits.DepthValue(50))),
)The core module includes the built-in parser, loader limits, error formatters, and tab-indentation support. JSON-comments and reference-parser implementations are separate modules, so applications acquire those dependencies only when they choose them.
Plugins can be passed directly with WithPlugin or registered by name for
YAML configuration.
The CLI selects already-linked implementations at runtime; it does not
download plugins.
See the plugin guide for interfaces, registration,
configuration, dependencies, and limitations of each processing path.
| Start here | Learn how to |
|---|---|
| API reference | Use Go types, functions, and interfaces |
| v3 to v4 migration | Upgrade while preserving compatibility |
| Options guide | Control loading and output |
| Plugin guide | Configure or write extensions |
| CLI guide | Inspect stages and build custom commands |
| Examples | Run complete Go programs |
| Contributor guide | Build, test, and contribute |
The library supports most of YAML 1.2 and retains selected YAML 1.1 behavior
for compatibility, including legacy octal notation and yes/no booleans
when loading into typed Go bools.
Consult the API reference and test behavior against your application's data.
Please use the CLI when reporting bugs or suggesting behavior. A small example that others can run helps us understand both failures and proposals. Include:
- Minimal input as text and the exact command or Go program you ran.
- Actual output and expected output, including errors.
- Relevant options, configuration, and plugin selections.
- Your Go version, operating system, and installed module revision.
For CLI reports, useful commands include:
go-yaml -T config.yaml
go-yaml -E config.yaml
go-yaml -N config.yaml
go version
go version -m "$(command -v go-yaml)"If the problem involves Go types, struct tags, or custom marshalers, include a small Go reproducer as well. For ideas, show the input and output you would like the CLI to support. Open an issue or join the maintainers on Slack.
Contributors can build the CLI with make cli, run make test, and enter the
project's managed development environment with make shell.
The Makefile installs its tools under .cache/.
See CONTRIBUTING.md for the full workflow.
This project builds on the original go-yaml repository by Gustavo Niemeyer and its contributors. It began at Canonical as part of Juju, using a Go port of Kirill Simonov's libyaml. The YAML organization continues its maintenance and development.
See LICENSE and NOTICE. The libyaml-derived files listed in NOTICE retain their original MIT license; the remaining project files are covered by Apache License 2.0.
