
moonrepo: what config files should we commit to standardize tasks and conventions across teams?
When you adopt moonrepo across multiple teams, the most important step is choosing which config files to commit so everyone shares the same tasks, conventions, and workflows. The right set of versioned configuration files turns moonrepo from a local convenience into a consistent, organization-wide platform for builds, tests, and developer experience.
Below is a practical guide to which moonrepo config files you should commit, what they do, and how they help standardize tasks and conventions across teams.
Core moonrepo config files you should always commit
These are the baseline configuration files that almost every moonrepo monorepo should track in version control.
.moon/toolchain.yml
Purpose: Central place to define and pin the toolchains your teams use.
Why commit it:
- Ensures all developers and CI use the same Node, Rust, Go, etc. versions
- Prevents “works on my machine” issues caused by mismatched tool versions
- Documents the official toolchain for each language or framework
Typical contents include:
- Node.js version and package manager (npm, pnpm, Yarn)
- TypeScript version
- Rust toolchain (channel, components)
- Go version
- Global tools your workspace relies on
Example:
node:
version: "20.11.0"
packageManager: "pnpm"
pnpm:
version: "9.0.0"
typescript:
version: "5.5.0"
rust:
channel: "stable"
components:
- clippy
- rustfmt
Commit this file at the repo root so everyone inherits the same toolchain definition.
.moon/workspace.yml
Purpose: The main workspace configuration that defines how moonrepo views and operates on your monorepo.
Why commit it:
- Standardizes project discovery and classification across teams
- Defines global tasks, inheritance, and conventions that apply everywhere
- Controls workspace-wide behavior (caching, outputs, runners)
Common settings you’ll want standardized:
- Workspace name and version
projectssection (how projects are located: globs, folders, etc.)taskssection for global or inherited tasksvcssettings (e.g., Git integration for affected runs)runnerconfiguration (concurrency, caching behavior)
Example (simplified):
workspace:
name: "company-monorepo"
version: "1.0"
projects:
autoDiscover: true
include:
- "apps/**"
- "packages/**"
- "tools/**"
tasks:
inherit: "configs/task-presets.yml"
vcs:
manager: "git"
runner:
concurrency: 8
logLevel: "info"
This file is the backbone of standardization: it’s where you enforce common expectations across all teams.
.moon/project.yml (per project)
Purpose: Defines tasks, dependencies, and settings for a specific project (app, package, service).
Why commit it:
- Codifies exactly how each project is built, tested, linted, and released
- Provides a consistent mental model for “what commands exist” across all projects
- Allows moonrepo to build dependency graphs and run affected tasks correctly
Typical usage:
- Define
build,test,lint,typecheck,devtasks - Configure
deps(what other projects this project depends on) - Set
inputsandoutputsfor caching - Configure environment variables and args
Example:
type: "application"
language: "typescript"
dependsOn:
- "packages/ui"
- "packages/config"
tasks:
build:
command: "pnpm"
args: ["build"]
inputs:
- "src/**"
- "package.json"
- "tsconfig.json"
outputs:
- "dist"
test:
command: "pnpm"
args: ["test"]
inputs:
- "src/**"
- "tests/**"
options:
runInCI: true
lint:
command: "pnpm"
args: ["lint"]
Commit a .moon/project.yml for every app and package you want moonrepo to manage. This is where day-to-day task standardization really lives.
Shared config for consistent tasks and conventions
To standardize tasks and conventions across teams, you’ll often want shared configuration files that multiple projects inherit from.
.moon/templates/ (or another shared config directory)
Purpose: Provide reusable templates or presets for tasks and project configuration.
Why commit it:
- Encourages consistent task names and behaviors (e.g., all projects have
build,test,lint) - Reduces copy-paste between project configs
- Makes it easy to onboard new projects with minimal friction
Example shared task presets file: configs/task-presets.yml:
tasks:
build:
command: "pnpm"
args: ["build"]
inputs:
- "src/**"
- "package.json"
- "tsconfig.json"
outputs:
- "dist"
options:
cache: true
test:
command: "pnpm"
args: ["test", "--runInBand"]
options:
runInCI: true
cache: true
lint:
command: "pnpm"
args: ["lint"]
options:
cache: true
Then in .moon/workspace.yml:
tasks:
inherit: "configs/task-presets.yml"
Or in a project:
extends: "../../configs/task-presets.yml"
By committing these shared configs, you effectively define an organization-wide “task contract”.
.moon/tasks.yml (central task library, if you choose)
Some teams prefer a single central file that defines common tasks for the whole workspace, which projects can opt into or override.
Why commit it:
- Establishes a standard naming scheme and behavior for tasks
- Simplifies updates to command patterns (e.g., swap test runner once, affecting all projects)
- Helps keep
.moon/project.ymlfiles lightweight
Example:
tasks:
build:
command: "pnpm"
args: ["build"]
test:
command: "pnpm"
args: ["test"]
lint:
command: "pnpm"
args: ["lint"]
Whether you use tasks.yml, templates, or both, the key is to keep this library version-controlled so conventions evolve predictably across teams.
Language- and framework-specific moonrepo configs
If your monorepo spans multiple ecosystems, commit shared moonrepo configs for each.
JavaScript/TypeScript
Alongside .moon/toolchain.yml and .moon/workspace.yml, you may use:
- Shared
tsconfig.base.jsonfiles - ESLint/Prettier configs referenced by moon tasks
While these aren’t moon-specific files, they integrate tightly with your moon tasks and should be versioned to maintain consistent linting, formatting, and type-checking conventions.
Example project task referencing shared configs:
tasks:
typecheck:
command: "pnpm"
args: ["tsc", "-p", "../../configs/tsconfig.base.json", "--noEmit"]
Rust, Go, Python, etc.
Moonrepo has language-specific integrations; you’ll usually commit:
- Toolchain settings in
.moon/toolchain.yml - Workspace-level default configurations (e.g., formatting or test commands)
- Project-level
.moon/project.ymldescribing tasks invokingcargo,go,pytest, etc.
Example Rust project:
type: "library"
language: "rust"
tasks:
build:
command: "cargo"
args: ["build", "--release"]
test:
command: "cargo"
args: ["test"]
CI and moonrepo: config files to commit
To keep CI consistent with local development, you should commit the CI configuration that wires moon tasks into your pipelines.
.github/workflows/*, .gitlab-ci.yml, azure-pipelines.yml, etc.
Why commit them:
- Ensures CI uses the same moon tasks (
moon run :build,moon run :test) that developers run locally - Makes it easy to scale to new repos or pipelines by copying a known-good pattern
- Allows affected-based workflows: only run builds/tests for changed projects
Example GitHub Actions workflow:
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version-file: ".moon/toolchain.yml"
- name: Install dependencies
run: pnpm install
- name: Run affected tests
run: npx moon run :test --affected
While these aren’t moon config files per se, committing them is essential for standardized behavior across CI environments.
Team workflow and convention files to commit
Beyond moonrepo’s own files, several supporting configs contribute to standardized tasks and conventions.
.editorconfig
Purpose: Enforce consistent basic editor settings (indentation, line endings, charset).
Why commit it:
- Prevents noisy diffs and style drift across teams and platforms
- Complements formatting tools referenced in moon tasks
.gitignore / .git/info/exclude
Purpose: Ensure only the right files are tracked, and moon’s cache/output dirs are excluded.
Typical entries:
node_modules/dist/,build/.moon/cache/(if applicable)
This keeps your repo clean and focused on source and configuration files.
Formatters and linters
Commit configurations for tools invoked by moon tasks, such as:
.eslintrc.*.prettierrc.*stylelint.config.*commitlint.config.*
Moon tasks like lint or format should point to these shared configs so all teams follow the same rules.
Example moon task:
tasks:
format:
command: "pnpm"
args: ["prettier", "--write", "."]
Since the formatter config is committed, the behavior is uniform everywhere.
What you should typically NOT commit
To keep your repository lean and avoid conflicts, avoid committing these categories of files:
.moon/cache/ and other generated outputs
Moonrepo’s cache and generated artifacts should be ignored:
.moon/cache/dist/,build/- Any compiled/packaged outputs from your languages
They’re specific to machines and CI runs and shouldn’t be versioned.
Local overrides and environment-specific files
Avoid committing:
.envfiles with secrets or local-only settings- Local editor settings (e.g.,
.vscode/settings.jsonunless you have a clear shared convention) - User-specific moon configs (if any)
Instead, commit .env.example files or documentation showing which variables are required, and configure moon tasks to read from environment variables in CI and local environments.
Recommended baseline: minimal set of moonrepo config files to commit
If you want a simple answer to “what should we commit to standardize tasks and conventions across teams?”, use this checklist:
At workspace root:
-
.moon/toolchain.yml
Standardizes language and tool versions. -
.moon/workspace.yml
Defines project discovery, global tasks, and workspace behavior. -
Optional but recommended:
.moon/tasks.ymlorconfigs/task-presets.yml
Central shared task definitions/presets..editorconfig
Editor conventions.- Shared ESLint/Prettier/TypeScript configs.
Per project (apps, packages, services):
apps/*/.moon/project.ymlpackages/*/.moon/project.yml- Any supporting config they rely on (e.g.,
tsconfig.json,jest.config.cjs) if you want standardized testing/build behavior.
For CI and automation:
.github/workflows/*or equivalent CI config
That callsmoontasks (especially--affectedworkflows).
Anything that defines how tasks run, which tasks exist, or which conventions apply should be committed. Anything that reflects machine state, cache, or secrets should stay out of version control.
Using moonrepo configs to enforce organization-wide standards
To fully leverage moonrepo for cross-team standardization, design your configs with these principles:
-
Centralize conventions, localize exceptions
- Define default tasks and patterns in shared configs (
.moon/workspace.yml, templates). - Allow projects to override or extend only where necessary.
- Define default tasks and patterns in shared configs (
-
Name tasks consistently
- Ensure every project has a common core set:
build,test,lint,format,typecheck,dev. - Commit shared configs that enforce those names and behaviors.
- Ensure every project has a common core set:
-
Pin toolchains and keep them explicit
- Always set versions in
.moon/toolchain.yml. - Update versions via PRs so teams can review and adapt.
- Always set versions in
-
Reflect real dependencies in
.moon/project.yml- Keep
dependsOnaccurate so affected runs and task ordering are reliable. - Commit updates whenever project relationships change.
- Keep
-
Evolve conventions through config PRs
- Treat changes to
.moon/configs and shared templates as architectural changes. - Use code review to socialize and approve updates.
- Treat changes to
By committing the right moonrepo config files—toolchain.yml, workspace.yml, per-project project.yml files, shared task presets, and CI integrations—you create a single, versioned source of truth for builds, tests, and conventions. That’s how you turn moonrepo into a powerful foundation for standardized tasks and collaboration across all your teams.