This guide demonstrates how to walk a CUE schema using the Go API, programmatically inspecting its structure and types.

The Go code shown here is a limited code generator which produces Go structs from simple CUE definitions. It could be adapted to other schema-walking tasks - not just code generation.

Initialize Go and CUE modules


Create a Go module, or use an existing one if that’s more suitable for your situation:

$ go mod init go.example

Create a CUE module if you don’t already have one:

$ cue mod init cue.example

The identifiers for the CUE and Go modules don’t need to match, but it doesn’t matter if they’re the same.

Declare a CUE schema


Declare the CUE schema that you wish to walk. We’ll use the following example.cue file, but you should use some CUE that’s specific to your situation.

package example

#Person: {
	name!: string
	age?:  int & >=0

#Address: {
	line1!:   string
	line2?:   string
	line3?:   string
	country?: string

aPerson: #Person & {
	name: "John Adams"

anAddress: #Address & {
	line1:   "1600 Pennsylvania Ave NW"
	line2:   "Washington, DC 20500"
	country: "United States of America"

someData: aValue:      42
_aHiddenField: aValue: 139

Our example.cue file contains two definitions that we want to process: #Person and #Address. It also includes concrete data fields and a hidden field, which we don’t consider as schema. The data and hidden fields are included in order to demonstrate that they are not processed by the code presented below.


Ensure there are no errors in our CUE:

$ cue vet

Use a Go program to walk the schema


Create the file main.go and add the following code:

package main

import (


func main() {
	ctx := cuecontext.New()

	// Load CUE from the package in the current directory
	insts := load.Instances([]string{"."}, nil)
	v := ctx.BuildInstance(insts[0])
	if err := v.Err(); err != nil {

	// "Render" the top-level struct definitions as Go types
	fmt.Printf("package p\n\n")

	it, err := v.Fields(cue.Definitions(true))
	if err != nil {
	for it.Next() {
		v := it.Value()
		if !it.IsDefinition() || v.IncompleteKind() != cue.StructKind {
		structToType(it.Selector(), it.Value())

// structToType prints the top-level fields of a struct value
func structToType(name cue.Selector, val cue.Value) {
	fmt.Printf("type %v struct {\n", strings.TrimPrefix(name.String(), "#"))

	// Iterate through the fields of the struct
	it, _ := val.Fields(cue.Optional(true))
	for it.Next() {
		switch k := it.Value().IncompleteKind(); k {
		case cue.StringKind, cue.IntKind, cue.FloatKind, cue.BoolKind:
			fmt.Printf("\t%v %v\n", it.Selector().Unquoted(), it.Value().IncompleteKind())


Add a dependency on and ensure the Go module is tidy:

$ go get
$ go mod tidy

You can use @latest in place of a specific version.


Run the Go program:

$ go run .
package p

type Person struct {
	name string
	age int
type Address struct {
	line1 string
	line2 string
	line3 string
	country string

As you can see from its output, this Go program is a very limited form of code generator that takes each CUE definition and produces a matching Go struct type.