Installation
moonctl is one MoonBit package. Use it as a library and the whole generator is a
function call; build the mctl command when you want the spec tools and
the project scaffolds too.
Requirements #
A MoonBit toolchain — moon — and git. The library builds for
all four targets; the command is a native binary, because it reads and writes files.
Check what you have:
$ moon version moon 0.1.20261023 (3778465 2026-10-23)
As a library #
Add the module to a MoonBit project:
$ moon add moonbitstack/moonctl
Import the package where you generate from:
import {
"moonbitstack/moonctl",
}
Parsing a spec gives a tree; generating reads that tree and returns a string:
let spec = @moonctl.parse(source) let code = @moonctl.generate(spec) // a moonapi scaffold, as text let tree = @moonctl.generate_tree(spec) // the layered project, file by file
There is no IO in the library, so it does not force a target on the project that imports it. A server, a build script, a browser page and a test can all call it.
The mctl command #
Build it from the repository:
$ git clone https://github.com/moonbitstack/moonctl $ cd moonctl $ moon build --target native --release
The binary lands in _build/native/release/build/cmd/mctl/ as
mctl — mctl.exe on Windows. Put that directory on your
PATH:
# bash, zsh $ export PATH="$PWD/_build/native/release/build/cmd/mctl:$PATH" # PowerShell > $env:PATH = "$PWD\_build\native\release\build\cmd\mctl;$env:PATH"
Check it #
mctl env prints the configuration it would use, and where each value came from:
$ mctl env config ~/.mctl/config home (bundled template library) remote https://github.com/moonbitstack/templates branch main style gozero templates (none pinned) working dir /home/you/shop
Then ask it for the commands it knows:
$ mctl help usage: mctl gen <api|rpc|model|crud|doc|gql|agent> <file> generate a project tree, models or a document from a spec mctl api <format|validate|doc|ts|dart|kt|java> <file.api> work on a .api spec itself: format it, check it, document it, or generate a client
Shell completion #
mctl completion writes a script for bash, zsh,
fish or powershell. The command table it completes from is the
same one that prints mctl help, so the two cannot disagree.
# bash $ mctl completion bash > ~/.local/share/bash-completion/completions/mctl # zsh, for the current shell $ source <(mctl completion zsh) # fish $ mctl completion fish > ~/.config/fish/completions/mctl.fish
Configuration #
Settings live in one small file — ~/.mctl/config, or
%USERPROFILE%\.mctl\config on Windows, or wherever
$MOONCTL_CONFIG points. Read and write it with the command rather than an
editor:
$ mctl config list version = 2 home = remote = https://github.com/moonbitstack/templates branch = main style = gozero $ mctl config set style go_zero mctl: style = go_zero in ~/.mctl/config $ mctl config get style go_zero
The keys:
| Key | What it sets | Default |
|---|---|---|
home | a template library on disk | empty — the bundled catalogue |
remote | a git remote holding a template library | https://github.com/moonbitstack/templates |
branch | the branch of remote | main |
style | how generated names are spelled | gozero |
templates | templates pinned to a version | none |
home, remote and branch are recorded, reported by
mctl env, and passed through the configuration — but generation still reads
the bundled template catalogue. Pinning a home directory today changes what
mctl template list reports, not what it writes.
Next #
Write a spec and generate a project from it. The whole loop takes three commands.