metago

command module
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 20, 2026 License: MIT Imports: 23 Imported by: 0

README

Metago

Metago

MIT License

Bring metaprogramming into Go.

Define a reusable Go template in a *.metago file:

{{/* stringer.metago */}}
{{ define "stringer" }}
func (v {{ name . }}) String() string {
	switch v {
	{{- range .Values }}
	case {{ .Name }}:
		return {{ quote .Name }}
	{{- end }}
	default:
		return "unknown"
	}
}
{{ end }}

Select it from Go source:

package example

// Status is the state of a job.
//mgo:gen stringer
type Status int

const (
	StatusPending Status = iota
	StatusRunning
	StatusDone
)

From the project root, run metago to automatically find all .metago templates and generate meta.go beside the source:

// Code generated by metago; DO NOT EDIT.

package example

func (v Status) String() string {
	switch v {
	case StatusPending:
		return "StatusPending"
	case StatusRunning:
		return "StatusRunning"
	case StatusDone:
		return "StatusDone"
	default:
		return "unknown"
	}
}

Installation

[!NOTE] Metago is early-stage software, so its APIs and directives may still evolve. Please open an issue if you see any bugs or strange behaviours.

Install the command directly:

go install github.com/guillemus/metago@latest

Ready-to-use binaries are also available on GitHub Releases.

With Go 1.24 or later, pin Metago as a project tool:

go get -tool github.com/guillemus/metago@latest

Add one go:generate directive at the project root:

//go:generate go tool metago .

Metago scans that root recursively. Run generation with:

go generate ./...
Agent skill

Install the Metago skill for supported coding agents with the Skills CLI:

npx skills add guillemus/metago --skill metago

Usage

metago              # scan the current directory recursively
metago ./path       # scan another root recursively
metago -v           # show verbose logs
metago --verbose

From the project root, metago is the normal invocation. It automatically discovers every .metago template beneath the scan root; do not name or pass template files. Metago is silent on success unless verbose logging is enabled. It skips vendor, testdata, and hidden directories. Template names come from {{ define "name" }} blocks and must be unique across the scan root. Names beginning with std. are reserved for Metago's standard templates.

Generation is atomic across the scan root. If any package fails, Metago changes no files. Successful runs remove stale Metago-generated sidecars and preserve other files.

Directives

Metago annotations start with //mgo: and contain no space after //. The form // mgo:gen stringer is ignored.

Sidecar generation

//mgo:gen writes generated declarations to a package sidecar:

// Status is the state of a job.
//mgo:gen stringer
type Status int

Ordinary source directives share meta.go. Internal test directives write meta_test.go; external <package>_test directives write meta_<package>_test.go.

Inline generation

//mgo:inline places generated code after its declaration:

//mgo:inline stringer
type Status string

func (s Status) String() string { return string(s) }

//mgo:end

Metago inserts //mgo:end and replaces the managed region on later runs. Treat generated sidecars and code between //mgo:inline and //mgo:end as read-only. Change the directive or template and rerun Metago instead of editing generated code.

Targets

A directive in a declaration's doc comment targets that declaration. Place declaration documentation before Metago directives:

// User represents an account.
//mgo:gen validator strict
//mgo:api owner=identity
type User struct{}

Every token after the template name in this anchored form is an argument. A standalone directive can name its target explicitly:

type Status string

//mgo:gen stringer Status

Types, methods, functions, package-level constants, and package-level variables can be targets. A directive in the package doc comment creates a package-scoped invocation:

//mgo:gen std.serde.jsonruntime
package jsonruntime

See the directive reference for standalone target resolution, const/var declarations, stacked directives, and inline placement.

Arguments and defaults

Arguments can be positional values, bare flags, or key=value pairs:

//mgo:gen endpoint /users/{userID} auth=required cache
func GetUser() {}

Read them with .Argv, .Args, or arg:

path: {{ arg 0 }}
auth: {{ default "public" (arg "auth") }}

An optional metago.toml at the project root configures default named arguments:

[templates."std.serde".args]
runtime = "example.com/project/internal/jsonruntime"

Explicit arguments on //mgo:gen and //mgo:inline override configured defaults.

Properties

A custom directive namespace attaches generator-specific metadata to a declaration:

// User represents an account.
//mgo:gen validator
//mgo:api owner=identity
type User struct {
	Name string `json:"name"` //mgo:validate required max=100
}

Read properties with prop, props, propHas, and propExists:

{{ range .Fields }}
{{ if propHas . "validate" "required" }}
// {{ .Name }} is required
{{ end }}
{{ end }}

Properties generate no code. Repeating a namespace merges flags and named values; later named values win. Put generation directives before property directives when stacking them in one comment block.

Templates

Each template receives metadata for its invocation and target:

{{ .Package.Name }}
{{ .Name }}
{{ .Kind }}
{{ .Fields }}
{{ .Methods }}
{{ .Values }}
{{ .Meta }}

Helpers cover names, types, tags, properties, imports, collections, and diagnostics:

{{ name . }}
{{ typeof . }}
{{ tagName . "json" }}
{{ imports "encoding/json" }}
{{ emitOnce "mytemplate.helper" }}
{{ fail "unsupported target" }}

imports adds an import and emits no text. Use emitOnce for declarations shared by several invocations in one generated output. fail rejects an unsupported invocation; Metago reports all template failures and changes no generated files if any invocation fails.

The template reference lists every metadata field and helper.

Package aggregation

A template can read generation directives for its package through .Package.Metas, ordered by file and line. This supports registries and other aggregate output:

{{ define "route" }}{{ end }}

{{ define "route-table" }}
var Routes = []string{
{{- range .Package.Metas }}
{{- if eq .Template "route" }}
	{{ quote (index .Argv 0) }},
{{- end }}
{{- end }}
}
{{ end }}

The empty route template produces no code, but its directives still appear in .Package.Metas. Property annotations are read from their attached symbols instead.

Standard templates

Metago embeds templates for common generation tasks:

Template Generates
std.stringer String() for a primitive-backed enum or ordinary value type
std.enum String conversion, parsing, validation, values, and JSON for enums.
std.mock Function-backed mocks for interfaces.
std.serde Reflection-free JSON codecs.
std.serde.jsonruntime The shared runtime used by std.serde.

See the standard-template guide for supported targets, options, and examples.

Documentation

  • Guide — learn the workflow from installation through reusable generators.
  • Examples — complete patterns ready to adapt.
  • Reference — directives, template data, helpers, and exact behavior.
  • Standard templates — built-in generators and their options.

Testing and development

Run the complete test and static-analysis suite:

go test ./...
staticcheck ./...

Golden fixtures live under testdata/. Update them only when intentionally accepting changed output:

UPDATE_GOLDEN=1 go test ./...

Regenerate this repository's checked-in Metago outputs with:

go run . .

Preview the documentation at http://localhost:3000:

mise run docs

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
experiments
std
serde
Package serde demonstrates codecs generated by std.serde using the shared generated runtime in the jsonruntime subpackage.
Package serde demonstrates codecs generated by std.serde using the shared generated runtime in the jsonruntime subpackage.
serde/jsonruntime
Package jsonruntime provides the shared runtime generated for std.serde codecs.
Package jsonruntime provides the shared runtime generated for std.serde codecs.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL