Lesson 0003 · ~12 minutes
One skill: walk the path from a moon binary to
moon run app:lint — install, moon init,
project discovery, then targets — without memorizing every config knob.
You can narrate the first-day sequence on a real repo: install moon, init the workspace, make projects visible, run a target — and know why “folder exists” ≠ “moon knows the project.”
moon ships as a single binary (install guide). Common paths:
proto install moon — multi-version; pin with
.prototools (e.g. moon = "2.0.0").
~/.moon/bin + put it on PATH.
@moonrepo/cli as a root devDependency. If both global
and repo package exist, the
repo package version wins when you invoke
moon — useful for pinning the team.
Upgrade later via proto install moon --pin or moon upgrade (for ~/.moon/bin installs).
After install:
setup workspace
+
moon init.
$ moon init
# prototype: moon init --minimal
.moon/ (or .config/moon) — the
workspace root
marker.
.moon/workspace.*.
.gitignore; infers VCS.
The workspace owns VCS integration, tree-wide config, the
project graph, and
running the action graph. moon needs a VCS (default git) for hashing and
affected runs — set vcs.defaultBranch if yours is
main not master.
A folder can sit in the repo and still be
invisible to moon until it appears under
projects in
.moon/workspace.*
((create a project).
Three patterns (all official):
client: 'apps/client' — stable IDs you type in targets.
- 'apps/*' — IDs from folder names (collision risk).
globs: + sources: for exceptions.
Check a project: moon project client. Wrong path → error.
Config tasks with shared
.moon/tasks/** and/or per-project moon.*
(lesson 2 inheritance still applies).
Everyday command:
moon run
(alias moon r).
Run a task spells the
pipeline:
deps, then the primary target.$ moon run app:build
$ moon run client:dev server:dev
$ moon run :test # all projects
$ moon run '~:test' # closest project (cwd)
$ moon run app:build --affected
$ moon run app:build -- --force # args after -- go to the tool
Default is fail-fast (one failure aborts the graph).
--affected only runs when VCS-touched files intersect the
task’s inputs — the anti-“full CI every push” lever from lesson 1.
proto / ~/.moon/bin / @moonrepo/cli
moon init → .moon/workspace.*
projects: map or globs → graph nodes
moon run scope:task → action graph + cache
Equal-length options. Retrieve the loop, not the whole manual.
You installed moon globally. What creates the workspace root?
apps/web exists with source, but
moon project web fails. Likeliest cause?
How do you run the lint task in project
app?
Why pass --affected to moon run?
Recommended path (in order): Install → Setup workspace → Create a project → Run a task.
Keep the loop sheet open when you try this on a real repo (optional hands-on; quiz first is fine).