Using the Moderne CLI
The Moderne CLI is a command line tool that complements the Moderne Platform and Moderne DX, enabling you to build Lossless Semantic Tree (LST) artifacts across many repositories and run recipes against all of them from your local machine. It also provides substantial benefits for creating and testing your own recipes.
The quickest way to see the CLI in action is the quickstart, where a coding agent drives mod for you. This guide is for when you want to run each step yourself, or need to understand what the agent is doing on your behalf. We will walk you through everything from installation, to configuration, to the commands that sync code, run recipes, and turn the results into pull requests.
The examples in this guide use the latest version of the Moderne CLI.
Installation and configuration
Choose the installation path that matches your setup:
- Standard Edition
- Enterprise Edition
- Moderne DX
These instructions apply to Standard Edition customers and users of the public app.moderne.io instance.
Install the CLI and log in
Run the install script for your operating system:
- Linux / macOS
- Windows
curl https://app.moderne.io/cli | bash
irm https://app.moderne.io/cli/windows | iex
You must use PowerShell for Windows installation. Git Bash, MSYS2, and Cygwin are not supported. The curl ... | bash command from the Linux / macOS tab will not work correctly in these environments.
The script installs a lightweight wrapper called modw, with mod as a symlink to it. It makes mod available in your terminal, points the CLI to app.moderne.io, and then opens your browser so you can authorize it. Sign in if you aren't already, then click Yes when asked whether the CLI can create a personal access token on your behalf.
Once you've confirmed, the CLI stores the token on your machine and then syncs the recipe marketplace so you can search and run recipes locally. The sync takes a few minutes.
By default, the token is valid for 365 days. When it expires, run mod login again to renew it. If you need a different expiration period, you can use the --expiration option (e.g., mod login --expiration P180D for 180 days).
On its first run, the wrapper downloads the CLI distribution for your platform and keeps it up to date. Verify the installation by running mod in your terminal:mod command results
The script also sets up tab completion for bash, zsh, and PowerShell. This means that if you open a new terminal and type mod and then press tab, you can see the list of available commands.
You can also install the CLI with Homebrew or Chocolatey. You will need to configure a few things yourself if you do. A package manager installs only the wrapper. You will need to connect the CLI to app.moderne.io and authorize it yourself: The login command opens your browser for the same authorization, then syncs the recipe marketplace. Shell completion is not set up for you either. To enable it for the current terminal, run: To enable it for every terminal you open, add that command to the bottom of your Homebrew and Chocolatey instructions
brew install moderneinc/moderne/modchoco install mod --prerelease~/.zshrc or ~/.bashrc file.
Refreshing the recipe marketplace
Authorizing the CLI syncs the recipe marketplace once. When Moderne publishes new recipes, you can sync it again:
mod config recipes moderne sync -y
Without -y, the command asks for confirmation before replacing the recipes you already have.
Occasionally, a few of the recipes may fail to sync properly and return the message ! Failed to install. If the majority of the recipes installed successfully, however, you will see the MOD PARTIALLY SUCCEEDED message when the command completes. Feel free to ignore that and continue with the tutorial.
If your organization is paying for the Enterprise Edition of Moderne and you have a private Moderne instance (e.g.,
https://yourcompany.moderne.io), please follow these instructions.
Install the CLI and log in
Run the install script for your operating system. Replace <TENANT> with your actual tenant name (e.g., yourcompany):
- Linux / macOS
- Windows
curl https://<TENANT>.moderne.io/cli | bash
irm https://<TENANT>.moderne.io/cli/windows | iex
You must use PowerShell for Windows installation. Git Bash, MSYS2, and Cygwin are not supported. The curl ... | bash command from the Linux / macOS tab will not work correctly in these environments.
The script installs a lightweight wrapper called modw, with mod as a symlink to it. It makes mod available in your terminal, points the CLI to your tenant, and then opens your browser so you can authorize it. Sign in if you aren't already, then click Yes when asked whether the CLI can create a personal access token on your behalf.
Once you've confirmed, the CLI stores the token on your machine and then syncs the recipe marketplace from your tenant so you can search and run recipes locally. The sync takes a few minutes.
By default, the token is valid for 365 days. When it expires, run mod login again to renew it. If you need a different expiration period, you can use the --expiration option (e.g., mod login --expiration P180D for 180 days).
On its first run, the wrapper downloads the CLI distribution for your platform and keeps it up to date. Verify the installation by running mod --version in your terminal.
The script also sets up tab completion for bash, zsh, and PowerShell. This means that, if you open a new terminal, type mod, and then press Tab - you should see a list of available commands that you can auto-complete.
You can also install the CLI with Homebrew or Chocolatey. You will need to configure a few things yourself if you do. A package manager installs only the wrapper. You will need to connect the CLI to your tenant and authorize it yourself: The login command opens your browser for the same authorization, then syncs the recipe marketplace. Shell completion is not set up for you either. To enable it for the current terminal, run: To enable it for every terminal you open, add that command to the bottom of your Homebrew and Chocolatey instructions
brew install moderneinc/moderne/modchoco install mod --prerelease~/.zshrc or ~/.bashrc file.
In a CI job or a container, there is no browser for the script to open. You can install and authorize the CLI unattended instead. If the CLI is already installed, you can log in with the token directly. The command reads the token from standard input:Unattended installation instructions
https://<TENANT>.moderne.io/settings/access-token (replace <TENANT> with your tenant name)MOD_TENANT_AUTHORIZATION environment variable when you run the install script:
Refreshing the recipe marketplace
Authorizing the CLI syncs the recipe marketplace once. When your tenant publishes new recipes, you can sync it again:
mod config recipes moderne sync -y
Without -y, the command asks for confirmation before replacing the recipes you already have.
Occasionally, a few of the recipes may fail to sync properly and return the message ! Failed to install. If the majority of the recipes installed successfully, however, you will see the MOD PARTIALLY SUCCEEDED message when the command completes. Feel free to ignore that and continue with the tutorial.
For Moderne DX, follow the deploying the CLI from an internal artifact repository guide.
Connecting to internal tools
If your organization installs the CLI from an internal artifact repository (common for Enterprise and DX deployments), follow our guide to deploying the CLI from an internal artifact repository.
If you also need to point the CLI at other internal tooling (a non-default Maven settings file, an internal Artifactory for recipes, etc.), see our guide to configuring the CLI to work with internal tools.
New recipe releases are published to the Code Genome Project rather than Maven Central. If you don't resolve recipes through an internal mirror, point the CLI at the Code Genome Project so you don't install stale releases.
Using the CLI
With installation and configuration complete, you're ready to use the CLI. This section will guide you through common workflows and commands.
For a hands-on tutorial using public repositories, check out our Moderne CLI workshop.
The Moderne CLI was not designed to run multiple commands simultaneously. Please only execute one command at a time.
Setting up your workspace
The most common (and recommended) way of using the Moderne CLI is to run recipes against pre-built LSTs that you download to your machine. For this path, you'll want to create a directory that you can clone the LSTs and code to:
mkdir /path/to/your/moderne/workspace
cd /path/to/your/moderne/workspace
It's also possible to run recipes on code you have already checked out on your machine – in which case you'll want to cd into that directory and then build the LSTs:
cd /path/to/your/repos
mod build .
Syncing Moderne organizations
If you already have repositories you want to work with checked out locally, skip to the building LSTs section.
Rather than needing to manually clone every repository you want to run a recipe against, Moderne offers the ability to download LSTs and code for pre-defined groups of repositories.
- Standard Edition
- Enterprise Edition
- Moderne DX
Viewing available organizations
To see what organizations you have access to in app.moderne.io, run the following command:
mod config moderne organizations show
You should see something like this:
Moderne CLI 4.11.0
⏺ Retrieving the configured organizations
ALL (56608)
Backend Services (7081)
API (217)
GraphQL (76)
RPC (36)
Frameworks (6779)
JVM Frameworks (4377)
Spring (1949)
Spring Boot (550)
...
Data & ML (2467)
...
Open Source (2235)
Apache (1164)
CNCF (137)
Eclipse Foundation (142)
...
Sample Estate (27)
Java Estate (8)
Java Services (4)
Legacy Java Apps (5)
JavaScript Estate (8)
JavaScript Services (5)
Legacy JavaScript Apps (4)
Python Estate (11)
Legacy Python Apps (6)
Python Services (6)
Platform Engineering (6559)
...
Downloading LSTs and code
Once you've decided what organization you want to clone, you can download the LSTs and code to your machine by running the following command:
mod git sync moderne /path/to/your/workspace --organization "<organization-name>" --with-sources
Make sure to replace the path and organization with the one you want. If you don't want to download the code and just want to download the LSTs, you can remove the --with-sources flag.
If you need to enter an SSH passphrase to clone repositories, please see our SSH keys with passphrases guide before continuing.
Viewing available organizations
To see what organizations you have access to in your Moderne tenant, run the following command:
mod config moderne organizations show
You should see something that looks similar to this (it will have your organizations instead):
Moderne CLI 4.11.0
⏺ Retrieving the configured organizations
ALL (56608)
Backend Services (7081)
API (217)
GraphQL (76)
RPC (36)
Frameworks (6779)
JVM Frameworks (4377)
Spring (1949)
Spring Boot (550)
...
Data & ML (2467)
...
Open Source (2235)
Apache (1164)
CNCF (137)
Eclipse Foundation (142)
...
Sample Estate (27)
Java Estate (8)
Java Services (4)
Legacy Java Apps (5)
JavaScript Estate (8)
JavaScript Services (5)
Legacy JavaScript Apps (4)
Python Estate (11)
Legacy Python Apps (6)
Python Services (6)
Platform Engineering (6559)
...
Downloading LSTs and code
Once you've decided what organization you want to clone, you can download the LSTs and code to your machine by running the following command:
mod git sync moderne /path/to/your/workspace --organization "<organization-name>" --with-sources
Make sure to replace the path and organization with the one you want. If you don't want to download the code and just want to download the LSTs, you can remove the --with-sources flag.
If you need to enter an SSH passphrase to clone repositories, please see our SSH keys with passphrases guide before continuing.
Working with organizations in DX
For Moderne DX customers, organizations are defined in your organization's repos.csv file (or in a repos-lock.csv file shared with you). It's up to your team to figure out the best way to distribute this file. That being said, we'd recommend having your mass ingest pipeline publish this CSV to S3 (or something similar) so people can easily download this file to their machines.
Once you have the CSV downloaded, you can either clone all of the repositories in that file and then cd into the organization (a specific directory) you care about – or you can filter the CSV file down to just the ones you care about and then clone those.
In either case, the command you should run is:
mod git sync csv /path/to/your/workspace repos.csv --with-sources
If you don't want to download the code and just want to download the LSTs, you can remove the --with-sources flag.
Building LSTs
If you need to build the LSTs locally rather than downloading them, you can run the following command:
mod build /path/to/your/workspace
If a project fails to build, it might require additional configuration. See mod config build for customization options. If an LST doesn't build, running a recipe will just skip that project rather than error on it.
Make sure the build tools your projects use are on your PATH. Run mod doctor to see which toolchains the CLI finds on this machine.
Analyzing build results locally
When building LSTs for many repositories, some may fail due to unique build requirements. The Moderne CLI includes a built-in analytics dashboard for visualizing build failures. Launch it with:
mod trace builds analyze . --last-build

The dashboard displays build metadata and lets you drill into individual repositories to view logs and troubleshooting suggestions.
Running recipes
Once you have the LSTs downloaded or built, you can then run recipes against them.
Basic recipe execution
To run a recipe against all repositories in a specific directory:
mod run /path/to/your/workspace --recipe <RecipeName>
## For example:
mod run /path/to/your/workspace --recipe DependencyVulnerabilityCheck
If multiple recipes have similar names, you'll be prompted to select the specific one you want. You can avoid this by using the fully qualified recipe name such as in the following example:
mod run . --recipe org.openrewrite.java.dependencies.DependencyVulnerabilityCheck
Running recipes with parameters
Some recipes accept parameters to customize their behavior:
mod run /path/to/your/workspace --recipe <RecipeName> -P<parameterName>=<value>
## For example:
mod run . --recipe FindMethods -PmethodPattern="java.util.List add(..)"
Examining results
To learn more about what changed, you can command/ctrl click on the Fix results link in the output.
Working with data tables
Many recipes produce data tables on top of changing the code. Think of data tables as spreadsheets that recipes create to show you patterns and insights they discovered while analyzing your code.
Viewing available data tables
After running a recipe, the CLI will suggest data tables you can examine such as in the following example:
⏺ What to do next
> Run mod study to examine the following data tables produced by this recipe:
> mod study . --last-recipe-run --data-table VulnerabilityReport
> mod study . --last-recipe-run --data-table MavenMetadataFailures
> mod study . --last-recipe-run --data-table RecipeRunStats
> mod study . --last-recipe-run --data-table SourcesFileResults
Generating data tables
To generate a data table from the last recipe run, you can copy one of the commands listed after a recipe run. It should look something like this:
mod study /path/to/your/workspace --last-recipe-run --data-table <TableName>
This command will generate a CSV file that you can then analyze.
Customizing output format
You can use the Moderne CLI to output other types of data based on your needs. For instance, you may want it to create a markdown file or a JSON file instead. Below are some examples of how you can change the output format:
Export specific columns as JSON:
mod study . --last-recipe-run --data-table <TableName> --json <column1>,<column2>
Use templates for custom formatting:
mod study . --last-recipe-run --data-table MethodCalls --json sourceFile,method --template '{{"# Search results\n\n"}}{{range .}}{{"* "}}{{.sourceFile}}{{"\n```\n"}}{{.method}}{{"\n```\n"}}{{end}}' > methods.md
This flexibility allows you to create custom reports tailored to your organization's needs.
Committing changes and creating PRs
After running recipes, you'll typically want to review, test, and commit the changes. The CLI provides commands to help manage these changes across multiple repositories.
Creating branches
After running a recipe, the changes exist only as patches (so if you cd into any of the repos, you would see no changes). While you could apply the patches to the branches you have checked out, it's generally preferable to make changes inside of a new branch and then submit a PR for said branch:
mod git checkout /path/to/your/workspace -b <branch-name> --last-recipe-run
This creates a new branch in each repository that has changes from the recipe run.
Applying changes
To apply the recipe changes to your repositories, run the following command:
mod git apply /path/to/your/workspace --last-recipe-run
After applying changes, you can navigate to individual repositories and run git status to see the uncommitted changes. This is a good time to run tests and verify the changes work as expected.
Staging and committing changes
Once you've tested the changes and decided you want to commit them, you'll need to run the following command to stage the changes for commit:
mod git add /path/to/your/workspace --last-recipe-run
Then you can commit the changes:
mod git commit /path/to/your/workspace -m "<your commit message>" --last-recipe-run
Creating pull requests
After committing changes, you can push them and create pull requests:
Push changes to remote:
mod git push /path/to/your/workspace --last-recipe-run
If needed, you can also set the upstream tracking reference:
mod git push /path/to/your/workspace --last-recipe-run -u
You can also create PRs using the GitHub CLI:
mod exec . --last-recipe-run -- gh pr create --title "<PR title>"
For more options, see the CLI reference documentation.
Uninstalling the CLI
How you remove the CLI depends on how you installed it.
- macOS/Linux
- Windows
- Homebrew or Chocolatey
-
Delete the CLI directory:
rm -rf ~/.moderne/cli -
Delete any
modandmodwlinks the installer created in~/.local/bin,~/bin, or/usr/local/bin:rm -f ~/.local/bin/mod ~/.local/bin/modw -
If the installer added
~/.moderne/cli/binto yourPATH, remove that line and thecompletion.bashline from your shell configuration file (such as~/.zshrcor~/.bashrc).
-
Delete the CLI directory:
Remove-Item -Recurse -Force "$env:USERPROFILE\.moderne\cli" -
Remove
%USERPROFILE%\.moderne\cli\binfrom your userPathenvironment variable.
- Homebrew:
brew uninstall mod - Chocolatey:
choco uninstall mod
Removing the CLI leaves your access tokens and other data in the ~/.moderne directory (%USERPROFILE%\.moderne on Windows). Delete that directory too if you want a clean slate.
Additional information
If you want to learn more about the Moderne CLI, we'd encourage you to check out the following docs:
Or watch the following videos:
Differences between the Moderne CLI and the OpenRewrite build plugins
The OpenRewrite build plugins are designed to run a single recipe on a single repository at a time. When you run a recipe using these plugins, a new LST is produced regardless of whether or not the code for that repository has changed. This LST is temporarily stored in memory and used by the recipe before being discarded at the end of the recipe run. For large projects, this can be problematic as the entire LST must fit in memory for the recipe to work.
In contrast, the Moderne CLI is designed for scale. You can run recipes against multiple repositories at once and the LST does not need to fit into memory. This is because the Moderne CLI uses proprietary code to build the LST up in parts and then serializes/writes it to the disk (as part of the mod build command). Likewise, the mod run command will read this LST from the disk in pieces as it runs recipes rather than building the LST every time.
When running the Moderne CLI commands for the first time, you might notice that running a single recipe on a single repository is slower than the OpenRewrite build plugins. This is due to the fact that the OpenRewrite build plugins do not serialize the LST and write it to disk.
However, if you wanted to run more recipes against the same LST, you would see that the Moderne CLI drastically increases in speed compared to the OpenRewrite build plugins as the Moderne CLI can read the pre-built LST and execute recipes against it rather than having to build it again each time. Furthermore, if you wanted to, you could use the Moderne CLI to run a recipe against many repositories at once – which the OpenRewrite build plugins can't do.