Skip to main content
Even though you’ve created tasks, they’re not useful unless you run them. Tasks are executed with the moon run <target> command, which requires a target - the pairing of a scope and task name.

Basic Task Execution

To run a task, use the format <project>:<task>:
moon run app:build
In this example:
  • app is the project name
  • build is the task name
  • app:build is the target

What Happens When You Run a Task

When you execute moon run, the following happens:
1

Generate dependency graph

Moon generates a directed acyclic graph (DAG), known as the action graph.
2

Insert dependencies

All task dependencies (deps) are inserted into the graph.
3

Insert primary target

The primary target is inserted into the graph.
4

Execute in parallel

All tasks in the graph run in parallel and in topological order (dependency chain).
5

Check cache

For each task, moon calculates hashes and either:
  • Cache hit: Exit early and return the last run
  • Cache miss: Run the task and generate a new cache

Running Multiple Tasks

You can run multiple tasks at once:
moon run app:build app:test app:lint
Or run the same task across multiple projects:
moon run web:build api:build admin:build

Running Upstream Dependencies

moon always runs upstream dependencies (defined via deps) before running the primary target, as their outputs may be required:
moon.yml
tasks:
  build:
    command: 'vite build'
    deps:
      - '^:build'  # Build all dependencies first
When you run moon run app:build, moon will:
  1. Find all projects that app depends on
  2. Run build in those projects first
  3. Then run build in app

Running Downstream Dependents

If you’re working on a shared library and want to verify that downstream projects haven’t been broken, use the --downstream option:
moon run shared-lib:build --downstream
This will run:
  1. shared-lib:build
  2. All projects that depend on shared-lib and their build tasks
moon run shared-lib:build --downstream direct

Running Based on Affected Files

By default, moon run always runs the target, but relies on smart hashing and caching. If you’d like to only run a target when files have actually changed, use the --affected flag:
moon run app:build --affected
Moon will:
  • Extract locally changed files from your VCS (git)
  • Exit early if no files intersect with the task’s inputs
  • Only run tasks that are affected by the changes

Using Remote Changes

To determine affected files based on remote changes instead of local changes:
moon run app:build --affected remote
This compares the current HEAD against the vcs.defaultBranch configured in your workspace.

Filtering by Change Status

Filter affected files based on their change status:
# Only files that were deleted
moon run app:build --affected --status deleted

# Multiple statuses
moon run app:build --affected --status deleted --status modified
Available status values:
  • added - Newly created files
  • deleted - Removed files
  • modified - Changed files
  • staged - Files in git staging area
  • unstaged - Modified but not staged files
  • untracked - Files not tracked by git

Passing Arguments to Commands

To pass additional arguments to the underlying task command beyond the defined args, use -- followed by your arguments:
moon run app:test -- --coverage --verbose
These arguments are appended as-is to the command.
The -- delimiter and any arguments must be defined last on the command line.

Advanced Run Targeting

moon provides powerful targeting capabilities for advanced workflows:

Run a Task in All Projects

Omit the project name to run a task across all projects:
moon run :build
This runs the build task in every project that defines it.

Run Tasks Based on Queries

Use the --query option to filter projects:
# Run in all JavaScript/TypeScript projects
moon run :build --query "language=[javascript, typescript]"

# Run in all application projects
moon run :test --query "layer=application"

# Complex queries
moon run :lint --query "language=typescript AND layer=library"

Run Tasks Based on Tags

If your projects define tags, you can target them:
moon run :test --query "tags~frontend"

Run in Affected Projects Only

Combine :build with --affected to run only in affected projects:
moon run :build --affected
This is extremely useful in CI to only build/test what changed!

Common Run Patterns

Here are some common patterns:
moon run :build

CI/CD Usage

In continuous integration, you typically want to only run tasks for affected projects:
# GitHub Actions example
moon run :build :test :lint --affected remote --status modified --status added
This will:
  1. Compare against the default branch (e.g., main)
  2. Only run tasks in projects with modified or added files
  3. Leverage the dependency graph to ensure dependencies are built first
  4. Use remote caching to speed up builds

Task Output

When running tasks, moon provides detailed output:
$ moon run app:build

▪▪▪▪ app:typecheck | cached
████ app:build (2.3s)
  • cached - Task was cached and not re-run
  • (2.3s) - Task execution time
  • Progress indicators show running status

Verbose Output

For more detailed output, use the --log flag:
moon run app:build --log trace
Available log levels:
  • error - Only errors
  • warn - Warnings and errors
  • info - General information (default)
  • debug - Detailed debug information
  • trace - Very verbose trace information

Next Steps

moon run Reference

Complete reference for the moon run command

Task Concepts

Learn more about how tasks work in moon

Caching

Understanding moon’s smart caching system

CI/CD Setup

Configure moon for continuous integration

Build docs developers (and LLMs) love