Skip to main content
A target is a compound identifier that pairs a scope to a task, separated by a :, in the format of scope:task.

Overview

Targets are the primary way to reference and run tasks in moon. They combine:
  • A scope - which project(s) to run in
  • A task - which command to execute
Targets are used by terminal commands:
$ moon run designSystem:build
And configurations for declaring cross-project or cross-task dependencies:
tasks:
  build:
    command: 'webpack'
    deps:
      - 'designSystem:build'

Common Scopes

These scopes are available for both running targets and configuring them.

By Project

The most common scope is the project scope, which requires the name of a project, as defined in .moon/workspace.yml. When paired with a task name, it will run a specific task from that project.
# Run `lint` in project `app`
$ moon run app:lint

# Run `build` in project `api`
$ moon run api:build

# Run `test` in project `shared-utils`
$ moon run shared-utils:test
In configuration:
moon.yml
tasks:
  build:
    command: 'webpack'
    deps:
      - 'design-system:build'
      - 'api-client:build'

By Tag

Another way to target projects is with the tag scope, which requires the name of a tag prefixed with #, and will run a specific task in all projects with that tag.
# Run `lint` in projects with the tag `frontend`
$ moon run '#frontend:lint'

# Run `test` in projects with the tag `backend`
$ moon run '#backend:test'

# Run `build` in projects with the tag `library`
$ moon run '#library:build'
Because # is a special character in the terminal (is considered a comment), you’ll need to wrap the target in quotes, or escape it like so \#.
Define tags in projects:
packages/ui/moon.yml
tags:
  - 'frontend'
  - 'react'
  - 'library'

tasks:
  build:
    command: 'tsup'

Run Scopes

These scopes are only available on the command line when running tasks with moon run or moon ci.

All Projects

For situations where you want to run a specific target in all projects, for example linting, you can utilize the all projects scope by omitting the project name from the target: :lint.
# Run `lint` in all projects
$ moon run :lint

# Run `test` in all projects
$ moon run :test

# Run `typecheck` in all projects
$ moon run :typecheck
This is particularly useful for CI pipelines where you want to validate all code.

Closest Project ~

If you are within a project folder, or an arbitrarily nested folder, and want to run a task in the closest project (traversing upwards), the ~ scope can be used.
# From within packages/api/src/
$ moon run '~:test'
# Runs test in the 'api' project

# From within packages/api/src/controllers/
$ moon run '~:build'
# Still runs build in the 'api' project
Because ~ is a special character in the terminal (tilde expansion), you’ll need to wrap the target in quotes, or escape it like so \~.

Config Scopes

These scopes are only available when configuring a task.

Dependencies ^

When you want to include a reference for each project that’s depended on, you can utilize the ^ scope. This will be expanded to all depended on projects. If you do not want all projects, then you’ll need to explicitly define them.
moon.yml
dependsOn:
  - 'apiClients'
  - 'designSystem'

# Configured as
tasks:
  build:
    command: 'webpack'
    deps:
      - '^:build'

# Resolves to
tasks:
  build:
    command: 'webpack'
    deps:
      - 'apiClients:build'
      - 'designSystem:build'
This is extremely powerful for ensuring all dependencies are built before the current project.
Real-world example:
apps/web/moon.yml
language: typescript

dependsOn:
  - 'ui'
  - 'utils'
  - 'api-client'

tasks:
  build:
    command: 'vite build'
    deps:
      - '^:build'  # Automatically builds ui, utils, and api-client first
    outputs:
      - 'dist'

Owning Project ~

When referring to another task within the current project, you can utilize the ~ scope, or omit the ~: prefix altogether, which will be expanded to the current project’s name. This is useful for situations where the name is unknown, for example, when configuring .moon/tasks/**/*, or if you just want a shortcut!
.moon/tasks/all.yml
# Configured as
tasks:
  lint:
    command: 'eslint'
    deps:
      - '~:typecheck'
      # OR
      - 'typecheck'
  typecheck:
    command: 'tsc'

# Resolves to (assuming project is "foo")
tasks:
  lint:
    command: 'eslint'
    deps:
      - 'foo:typecheck'
  typecheck:
    command: 'tsc'
Both forms are equivalent:
moon.yml
tasks:
  test:
    command: 'jest'
    deps:
      - '~:typecheck'  # Explicit self-reference
      - 'lint'         # Implicit self-reference
  
  typecheck:
    command: 'tsc'
  
  lint:
    command: 'eslint'

Target Patterns

Parallel Execution

Run multiple targets in parallel:
# Run tests in multiple projects simultaneously
moon run app:test api:test shared:test

# Run different tasks in parallel
moon run app:lint app:typecheck app:test

Sequential with Dependencies

Tasks with deps run sequentially:
moon.yml
tasks:
  validate:
    deps:
      - 'typecheck'
      - 'lint'
  
  build:
    command: 'webpack'
    deps:
      - 'validate'
      - '^:build'

Complex Dependency Graphs

apps/web/moon.yml
tasks:
  build:
    command: 'vite build'
    deps:
      - '~:typecheck'           # Own typecheck
      - '~:lint'                # Own lint
      - '^:build'               # All dependencies' build
      - 'api-client:build'      # Specific dependency
      - '#backend:health-check' # All backend services

Real-World Examples

Monorepo CI Pipeline

# Type check everything
moon run :typecheck

# Lint all frontend projects
moon run '#frontend:lint'

# Test all backend projects
moon run '#backend:test'

# Build all libraries
moon run '#library:build'

# Build all applications (which will build their dependencies)
moon run '#app:build'

Local Development

# From within a project directory
cd packages/ui

# Run tests in current project
moon run '~:test'

# Start dev server for current project
moon run '~:dev'

# Build current project and dependencies
moon run '~:build'

Complex Build Dependencies

apps/web/moon.yml
language: typescript
stack: frontend

dependsOn:
  - 'ui'
  - 'utils'
  - 'api-client'

tasks:
  # Development server with full dependency chain
  dev:
    command: 'vite'
    deps:
      - '^:build'  # Build all dependencies first
    preset: 'server'
  
  # Production build with validation
  build:
    command: 'vite build'
    deps:
      - '~:typecheck'     # Type check this project
      - '~:lint'          # Lint this project
      - '^:build'         # Build all dependencies
      - 'api:health'      # Ensure API is available
    outputs:
      - 'dist'
  
  # Full validation suite
  validate:
    deps:
      - '~:typecheck'
      - '~:lint'
      - '~:test'
      - '^:validate'      # Validate all dependencies too

Special Characters Reference

CharacterScopeUsageExample
:SeparatorSeparates scope from taskapp:build
#TagRun task in all projects with tag#frontend:test
^DependenciesRun task in all project dependencies^:build
~Self/ClosestCurrent or closest project~:typecheck
(none)All projectsRun task in all projects:lint

Best Practices

Always use ^:build in build tasks to ensure all dependencies are built first. This is essential for proper dependency ordering.
Use tags to group projects by purpose (frontend, backend, library) and run tasks across logical groups instead of all projects.
Instead of :test (all projects), use #library:test or specific targets. This is faster and more intentional.
When defining tasks in .moon/tasks/, use ~: prefix to make tasks work regardless of project name.

Configuration Reference

For detailed configuration options, see:

Build docs developers (and LLMs) love