Skip to main content

Install moon

5 min

The following guide can be used for adding moon to an existing repository (with incremental adoption), or to a fresh repository. All that's required is...

  • Node.js and basic knowledge of the ecosystem
  • git >= 2.20, a version control system
  • A package.json in your repository root
git init ./app
cd ./app
npm init

Choosing a package manager

Before we install moon, we should briefly talk about Node.js package managers. To start, moon does not replace a package manager, nor does it apply any "magic" for them to work differently. Instead, moon builds upon a package manager to provide a robust build system, assumes a standard node_modules layout and module resolution algorithm, and supports any of the following 3 package managers.

We suggest Yarn 3 for its powerful workspaces implementation, extensive support for native binaries, built-in package patching, and blazing speed, but feel free to choose the one that works best for you!

Enabling workspaces

moon was built with monorepos in mind, and as such, has first-class support for them through package workspaces (but is not a requirement). To utilize workspaces, enable them for your chosen package manager.

package.json
{
// ...
"workspaces": ["apps/*", "packages/*"]
}
.yarnrc.yml
# ...
nodeLinker: 'node-modules'

Installing the CLI

The entirety of moon is packaged and shipped as a single binary through the @moonrepo/cli npm package. Begin by installing this package at the root of the repository.

yarn add --dev @moonrepo/cli

Accessing the moon binary

For developers, we suggest installing the @moonrepo/cli package globally, so that you can easily run moon commands from any directory, instead of relying on package.json scripts. When using this approach, the global must be installed with npm (not pnpm or yarn)!

npm install -g @moonrepo/cli

Don't worry though, when using the global binary, we ensure the same version of moon is being executed that was defined as a dependency in the repo.

Adding a package script

For other scenarios or environments, like CI, moon can be ran with through a package.json script -- but this comes with a cost -- which is the overhead of launching Node.js and your chosen package manager to execute the Rust binary, instead of executing the Rust binary directly. If this is problematic, feel free to use the global approach above.

package.json
{
// ...
"scripts": {
// ...
"moon": "moon",
// For Yarn 2+
"moon": "$(yarn bin moon)"
}
}
caution

Yarn 2+ does not support executing Rust binaries through package scripts (issue), so we must access the full binary path and execute on that.

With this script, moon can then be run with npm run moon ... (or yarn run, or pnpm run), but do note that this pattern will not work with package workspaces unless the script is ran from the repository root.

Supported targets

Because moon is written in Rust, we only support targets that are explicitly compiled for, which are currently:

  • macOS 64-bit - Intel (x86_64-apple-darwin)
  • macOS 64-bit - Silicon (aarch64-apple-darwin)
  • Linux 64-bit - GNU - Intel (x86_64-unknown-linux-gnu)
  • Linux 64-bit - musl - Intel (x86_64-unknown-linux-musl)
  • Linux 64-bit - GNU - Arm (aarch64-unknown-linux-gnu)
  • Linux 64-bit - musl - Arm (aarch64-unknown-linux-musl)
  • Windows 64-bit (x86_64-pc-windows-msvc)

Initializing moon

Now that we have the CLI installed, let's scaffold and initialize moon in a repository with the moon init command. Be sure to access the binary as mentioned above.

$ moon init

When executed, the following operations will be applied.

  • Creates a .moon folder with associated .moon/workspace.yml, .moon/toolchain.yml, and .moon/project.yml configuration files.
  • Appends necessary ignore patterns to the relative .gitignore.
  • Infers the Node.js version from any .nvmrc or .node-version file.
  • Infers the package manager based on any existing config and lock files.
  • Infers the package manager version from the packageManager field in package.json.
  • Infers projects from the workspaces field in package.json.
  • Infers the version control system from the environment.

Next steps