moonrepo quickstart: what are the exact steps to get it running in an existing monorepo?
Developer Productivity Tooling

moonrepo quickstart: what are the exact steps to get it running in an existing monorepo?

8 min read

Most teams discover Moonrepo after they already have a working monorepo and just want the exact steps to plug it in without breaking anything. This guide walks through a practical, copy‑pasteable quickstart for getting Moonrepo running in an existing monorepo, including configuration, task migration, and basic verification.


1. Prerequisites and assumptions

Before you start, make sure:

  • You already have an existing monorepo (e.g. with JavaScript/TypeScript, Rust, Go, etc.)
  • You have:
    • Node.js (for most setups)
    • Git (Moon uses Git metadata)
    • A terminal and permission to install binaries

Optional but recommended:

  • A package manager set up (pnpm, npm, yarn, bun)
  • CI access (GitHub Actions, GitLab CI, CircleCI, etc.) for later integration

Note: These steps are written to be minimal and safe to try. You can add Moonrepo alongside your current workflow and gradually migrate tasks.


2. Install Moonrepo CLI in your repo

The easiest and most portable way is via the official installer script. From the root of your monorepo:

curl -fsSL https://moonrepo.dev/install.sh | bash

This will:

  • Download the Moon binary into ./.moon/bin by default
  • Create a small shell wrapper so you can run moon directly

If you want it in node_modules/.bin instead (for JS-centric repos):

curl -fsSL https://moonrepo.dev/install.sh | bash -s -- --node

Verify installation:

moon --version

You should see a version output; if not, ensure ./.moon/bin (or the correct path) is on your PATH, or call it directly:

./.moon/bin/moon --version

3. Initialize Moonrepo in an existing monorepo

From the root of your repo:

moon init

You’ll be prompted for a few options (these may evolve, but in general):

  • Language / ecosystem (e.g. node, typescript, rust, etc.)
  • Project layout (e.g. packages/*, apps/*, services/*)
  • Whether to create example configs

If you want a non-interactive quickstart, you can pass flags, for example:

moon init --language node --preset node --yes

After running, you should see something like:

  • moon.yml – workspace-level config
  • .moon/ – Moon’s internal cache and binaries (do not commit the whole directory; only what docs suggest)
  • Possibly some starter task files like .moon/tasks.yml (depending on options)

4. Understand Moonrepo’s basic concepts (in 2 minutes)

You can get productive without knowing everything, but these fundamentals are key:

  • Workspace (moon.yml)
    Defines:

    • Project conventions (how Moon detects packages/apps)
    • Global tasks
    • Tools configuration
  • Projects
    Each app/package is a “project” (e.g. packages/api, apps/web). Moon can auto-detect them from package manifests or config files.

  • Tasks
    Named commands like lint, test, build, typecheck. They can:

    • Run in multiple projects at once
    • Be cached and only re-run when inputs change
    • Be wired into dependency graphs

You’ll mainly touch:

  • moon.yml
  • Per-project task config (for JS this is often package.json plus Moon conventions, or a moon.yml per project)

5. Configure project detection for your existing layout

Open the generated moon.yml at your repo root. For a typical JavaScript/TypeScript monorepo, a common structure is:

apps/
  web/
  admin/
packages/
  ui/
  api/

Configure Moon to recognize these projects. A simple moon.yml might look like:

# moon.yml
projects:
  # Automatically detect Node/JS projects by package.json
  - id: "apps"
    source: "apps/*"
    language: "javascript"
  - id: "packages"
    source: "packages/*"
    language: "javascript"

# Optional: set Node-specific settings
node:
  packageManager: "pnpm" # or "npm" | "yarn" | "bun"
  version: "22.0.0"      # or whatever your team uses

For other ecosystems:

  • Rust: use Cargo.toml-based detection
  • Go: use Go module layout
  • Polyglot: you can mix multiple projects entries with different language values

Run a quick detection check:

moon query projects

You should see a list of detected projects. If some are missing:

  1. Confirm source globs in moon.yml match your folder layout.
  2. Ensure each project has a recognizable manifest (package.json, Cargo.toml, etc.) or define a per-project moon.yml inside those directories.

6. Mirror your existing scripts as Moon tasks

To get value quickly, start by mapping the scripts you already use (NPM scripts, Make targets, etc.) into Moon tasks.

6.1 Identify your common commands

Look at package.json files (for JS) or your CI configuration and list:

  • lint
  • test
  • build
  • dev / start
  • typecheck

Example package.json:

{
  "scripts": {
    "lint": "eslint .",
    "test": "vitest",
    "build": "tsc -p tsconfig.build.json",
    "dev": "next dev"
  }
}

6.2 Create workspace-level tasks (optional but handy)

You can define tasks once and reuse them across projects. In moon.yml, add:

tasks:
  lint:
    command: "lint"
    platform: "node"
    options:
      runFromProject: true

  test:
    command: "test"
    platform: "node"
    options:
      runFromProject: true

  build:
    command: "build"
    platform: "node"
    options:
      runFromProject: true

This configuration tells Moon:

  • Run the lint task by invoking the project’s script named lint (usually npm run lint / pnpm lint).
  • Do it from within each project directory (runFromProject: true).

Alternatively, you can declare per-project moon.yml files if you need different commands per project.


7. Verify basic tasks across all projects

From the repo root, run:

moon lint

Moon will:

  • Detect all projects that have the lint task available
  • Run them, respecting the dependency graph and parallelism

Similarly:

moon test
moon build

If a task fails:

  • Check the output for the failing project path
  • Confirm that project actually has the underlying script/command you referenced
  • Adjust moon.yml or the project’s package.json as needed

8. Hook into your dependency graph

Moonrepo is powerful when it knows project dependencies (e.g. web depends on ui, api depends on shared).

For Node/TS monorepos using a package manager workspace (pnpm, yarn, npm workspaces), Moon can often infer the graph from package.json dependencies/devDependencies. If that’s your case, you may not need manual configuration.

If you want to be explicit (or are in a different ecosystem), you can add per-project config. Example apps/web/moon.yml:

type: "application"
dependsOn:
  - "packages/ui"
  - "packages/api"

Now running:

moon build apps/web

Will:

  • Build packages/ui
  • Build packages/api
  • Then build apps/web
    …in the correct order, using caching when possible.

9. Enable caching so tasks don’t re-run unnecessarily

Moon’s incremental task cache is a core feature. To leverage it, you need good inputs and outputs configuration so Moon knows when a task is “the same” and can be restored.

In moon.yml:

tasks:
  test:
    command: "test"
    platform: "node"
    inputs:
      - "src/**"
      - "tests/**"
      - "package.json"
      - "vitest.config.*"
    outputs:
      - "coverage/**"

Now:

  1. Run moon test once.
  2. Make no changes and run moon test again.

You should see logs indicating a cache hit and near-instant completion.

Customize inputs/outputs per task (workspace-level or per-project) for best results.


10. Add Moonrepo to CI without breaking your current pipeline

You don’t have to rewrite your CI all at once. Start by adding a Moon job in parallel or as an experiment.

Example GitHub Actions snippet:

name: CI

on:
  push:
    branches: [ main ]
  pull_request:

jobs:
  moon:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 22

      - name: Install Moon
        run: |
          curl -fsSL https://moonrepo.dev/install.sh | bash

      - name: Install dependencies
        run: pnpm install # or yarn install / npm ci / bun install

      - name: Run Moon tasks
        run: |
          moon lint
          moon test
          moon build

Once you’re comfortable, you can replace older ad‑hoc scripts with moon commands, benefitting from caching and consistent task orchestration.


11. Gradually migrate legacy scripts to Moon tasks

To integrate Moonrepo cleanly into an existing monorepo:

  1. Keep existing package.json scripts / Makefiles for now.
  2. Wrap them in Moon tasks so every common operation has a moon <task> equivalent.
  3. Start using Moon locally:
    • moon lint
    • moon test
    • moon build
  4. Update CI to use Moon for those steps.
  5. Once stable, you can:
    • Simplify or remove redundant scripts
    • Introduce more advanced Moon features (pipelines, target inheritance, more granular caching)

This incremental approach avoids big-bang refactors and allows the team to get comfortable with Moonrepo.


12. Quick checklist: exact steps in order

If you just want a short, actionable checklist for “moonrepo quickstart: what are the exact steps to get it running in an existing monorepo?”:

  1. From repo root, install Moon:

    curl -fsSL https://moonrepo.dev/install.sh | bash
    
  2. Initialize Moon workspace:

    moon init
    
  3. Edit moon.yml to:

    • Configure projects to match your apps/*, packages/*, etc.
    • (Optional) Set node.packageManager and node.version if using Node.
  4. Verify project detection:

    moon query projects
    
  5. Define core tasks in moon.yml (or per project), mapping to existing commands:

    tasks:
      lint:
        command: "lint"
        platform: "node"
        options:
          runFromProject: true
      test:
        command: "test"
        platform: "node"
        options:
          runFromProject: true
      build:
        command: "build"
        platform: "node"
        options:
          runFromProject: true
    
  6. Optionally set inputs/outputs to enable caching for tasks (e.g. for test and build).

  7. Run tasks across the monorepo:

    moon lint
    moon test
    moon build
    
  8. Configure dependency graph (if not auto-detected) via per-project moon.yml with dependsOn entries.

  9. Add Moon to CI, using moon lint, moon test, and moon build in your pipeline.

  10. Iterate: refine tasks, caching, and project configuration as your team adopts Moonrepo.

Follow these steps and you’ll have Moonrepo running smoothly in your existing monorepo with minimal disruption, ready to evolve into a more powerful, cache‑aware, graph‑driven workflow.