The moon command covers the normal development loop: create a project, check it, run it, test it, format it, and build an executable. This page focuses on those day-to-day workflows.
Run moon --help to see the available commands, or moon <command> --help for a command's options.
Create and run a project
Create a new directory with a starter project:
moon new my-app
cd my-app
moon run src/main.mnUse moon init instead when the directory already exists. A basic project has a moon.toml manifest and one or more .mn source files.
The three commands used most often are:
moon check src/main.mn
moon run src/main.mn
moon build -o my-app src/main.mncheck reports type and syntax errors without running the program. run checks and runs it. build keeps the resulting executable.
Arguments after -- go to the moon program:
moon run src/main.mn -- --port 8080Multiple project binaries
A project with several commands or services can declare each entry point in moon.toml:
[package]
name = "moon-service"
version = "0.1.0"
[[bin]]
entrypoint = "src/server.mn"
exe_name = "moon-server"
[[bin]]
entrypoint = "src/worker.mn"
exe_name = "moon-worker"Select a binary by name:
moon run --bin moon-server
moon check --bin moon-worker
moon build # build every declared binary
moon build --bin moon-server # build one binaryFor a directory of small commands, [bins] folder = "bins" discovers direct .mn children of that directory. Discovery is opt-in and does not recurse.
Testing
moon discovers zero-argument functions named test_* in *_test.mn files and under tests/ directories.
// calc_test.mn
use calc
fn test_add() {
std.testing.assert_eq(calc.add(2, 3), 5)
}Run all tests or narrow the run while working:
moon test
moon test calc_test.mn
moon test --filter add
moon test --listAsync test functions are supported too. Name tests that require a live service *_live_test.mn; they run only when explicitly selected or when --live is passed.
Formatting and linting
Format a file in place, check formatting without changing files, or format a directory recursively:
moon fmt --write src/main.mn
moon fmt --check .
moon fmt --write srcmoon lint reports unused names, unreachable code, shadowing, naming issues, and other code-quality suggestions:
moon lint .
moon lint --fix .
moon lint --deny-warnings .Project-wide formatting and lint choices can live in moon.toml:
[fmt]
indent = 2
line_width = 100
[lint]
enabled = true
todos = trueThe formatter and editor integration read the same project settings, so saved files and command-line checks agree.
Documentation
Write /// comments immediately above public declarations:
/// Adds two numbers.
pub fn add(left: int, right: int) -> int {
left + right
}Then render or browse documentation with:
moon doc source src/main.mn
moon doc std strings
moon doc builtin ArrayThe online API reference contains the same public APIs in a browsable form.
Packages
Dependencies are recorded in moon.toml and pinned in moon.lock.
moon add https://github.com/example/greeter.git --version ^1.2
moon update
moon deps
moon vendorImport a dependency through its package name:
use greeter.hello.greetCommit moon.lock for applications so teammates and deployments use the same versions. moon vendor is useful when a build must work without network access.
Project tasks
If a project needs a repeatable command beyond the built-in workflow, define a named task in a root build.mn:
fn main() {
std.build.emit([
std.build.task(
"check",
[std.build.process(["moon", "check", "src/main.mn"])],
),
])
}moon task --list
moon task checkTasks can depend on other tasks and run programs with declared inputs. Keep the common case small; add more orchestration only when the project needs it.
Editor support
moon ships a language server. Configure an editor to start:
moon lspIt provides diagnostics, completion, hover information, signature help, go-to-definition, references, rename, formatting, code actions, inlay hints, and project symbols. Editor integrations are available for VS Code, JetBrains IDEs, Neovim, and Zed.
Turn on format-on-save and use the project's moon.toml settings so local editing matches command-line checks.
A practical routine
For a typical change:
moon check
moon test
moon fmt --check .
moon lint .
moon buildYou rarely need every command for every edit. Run the checks that match the part of the project you changed, then build the binaries you plan to ship.