How to set up and use Go LSTs with the Moderne CLI
Moderne supports Go LSTs, enabling semantically-aware refactoring of Go code. With Go LSTs, recipes can resolve types, understand import graphs, and make precise automated changes across your Go repositories.
In this guide, we'll walk you through how to configure the Moderne CLI to take advantage of Go support.
As of CLI v4.5.0, the CLI parses Go out of the box, so most users don't need any moderne.yml changes to get started. If you're on an older CLI version or you use an explicit build.steps configuration, you'll need to add the Go build step manually.
Prerequisites
This guide assumes that:
- You have installed and configured the Moderne CLI (version
4.3.7or higher) - You are familiar with running Moderne CLI commands (if not, work through our CLI workshop)
- You have Go installed on your machine
Step 1: (Optionally) Configure your Go installation
By default, the CLI automatically detects the Go installation on your $PATH. The remaining configuration in this step is only needed if Go is installed in a non-standard location or if you want to constrain the memory used by the Go engine.
Discovering installations
You can see all detected and configured Go installations, in the order in which they will be selected, by running:
mod config go installation list
Adding installation locations
If Go is installed in a non-standard location, you can register it. Each path should point to either the Go installation directory or the go executable itself:
mod config go installation edit /usr/local/go
You can register multiple installations at once:
mod config go installation edit /usr/local/go /opt/go-1.24
To remove manually configured installation paths:
mod config go installation delete
This only removes user-configured paths. Automatically discovered installations remain available.
Setting the memory limit
The Go engine used to build LSTs and run recipes honors the GOMEMLIMIT soft memory limit, which defaults to 4GiB. To raise or lower it, run:
mod config build go gomemlimit edit 8GiB
The value accepts an integer with an optional B, KiB, MiB, GiB, or TiB suffix (for example, 512MiB), or off to disable the limit.
To see the currently configured limit:
mod config build go gomemlimit show
To revert to the default:
mod config build go gomemlimit delete
Step 2: (Optionally) Clone a custom list of repositories
If you don't have the repositories you want to work with cloned locally already, you can clone a group of them by defining a repos.csv file that lists them out such as in the following example:
cloneUrl,branch,origin,path
git@github.com:gorilla/mux.git,main,github.com,gorilla/mux
git@github.com:spf13/cobra.git,main,github.com,spf13/cobra
git@github.com:sirupsen/logrus.git,master,github.com,sirupsen/logrus
Check out our documentation on creating a repos.csv file for more detailed information about what's expected in this file.
After creating the CSV, clone the repositories by running the following command:
mod git sync csv . repos.csv --with-sources
Step 3: Build your Go repositories
The next thing you'll need to do is build LSTs for each of your repositories. To build the LSTs, run:
mod build /path/to/your/repos
Presuming everything has been set up correctly, you should see output similar to:
▶ gorilla/mux@main
Build output will be written to build.log
> Step 1 - build with Go
Selected Go 1.24.0
Processing Go module: .
Started project parsing: /Users/someuser/repos/gorilla/mux
Discovered 27 files to parse
✓ Built mux-20260213120000000-ast.jar
Cleaned 1 older builds
Step 4: Install recipes
In order to run recipes, you'll need to make sure the recipes are installed on your local machine. You can install a Go recipe module by specifying its module path with an optional version:
mod config recipes go install github.com/moderneinc/recipes-go
You can find the specific installation command for any recipe on its page in the recipe catalog.
Step 5: Run recipes
With the LSTs built and recipes installed, you can now run recipes against your Go repositories. You can either specify the full recipe path for running such as in:
mod run . --recipe=org.openrewrite.golang.RemoveUnusedImports
Or, you can search for a specific recipe and set it as the active recipe:
mod config recipes search RemoveUnusedImports
Then you can run the active recipe by:
mod run . --active-recipe
Step 6: View data tables
Many recipes will also produce useful data tables that you can access via the mod study command such as in:
mod study . --last-recipe-run --data-table SourcesFileResults
Moderne CLI 4.11.0
⏺ Reading organization
Found 1 organization containing 1 repository (1s)
Found recipe run 20260213120000-xYzAb
⏺ Building CSV output for each organization
▶ Go Repos
✓ Data table produced
Done (1s)
⏺ Converting to Excel for each organization
▶ Go Repos
✓ Data table produced
Done (2s)
Data tables for each organization with rows are linked above
Adding the Go build step manually
You only need this step if you're on a CLI version older than v4.5.0, or if you maintain an explicit build.steps list in a moderne.yml file. An explicit list replaces the default pipeline, so it must include - type: go for Go to be parsed. On CLI v4.5.0 and later with the default configuration, Go support is already enabled and you can skip this.
Update the build steps in the moderne.yml file that defines them. This is usually the global ~/.moderne/cli/moderne.yml file, which is created when you first set up the CLI, but a repository can also define its own steps in .moderne/moderne.yml (see choosing the configuration file).
If your moderne.yml file already includes a build section, add a - type: go step before the trailing resource step. If it doesn't, add the entire section as shown below:
# Other keys and values...
license:
key: some-license
tenant:
host: https://app.moderne.io
apiHost: https://api.app.moderne.io
skipSsl: false
authorization: Bearer mat-some-token
build:
steps:
- type: maven
- type: gradle
- type: bazel
- type: go
- type: resource
inclusion: |-
**/*
If you maintain an explicit configuration, start from the full default pipeline so you don't drop steps the CLI would otherwise run, such as sbt, javascript, and python.