Skip to content
tomaskyPublic

About

A MoonBit-native take on uv, fast toolchain and package manager for MoonBit

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

29 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mb

A MoonBit-native take on uv: a small, fast toolchain and package manager for MoonBit, written in MoonBit.

mb manages two things, mirroring how uv python / uv run / uv tool manage Python:

  • MoonBit toolchains — download, install and switch between compiler releases from cli.moonbitlang.com (mb moon ...).
  • Tools — install a prebuilt binary from a module's GitHub release, falling back to downloading a module from mooncakes.io and compiling it (mb tool ...).

Everything installs to ~/.local/bin by default. Only Linux (x86_64, aarch64) and macOS on Apple Silicon (arm64) are supported: the MoonBit toolchain no longer ships an Intel macOS target, so there is no darwin-x86_64 build.

Install

curl -LsSf https://raw.githubusercontent.com/tomasky/mb/main/install.sh | bash

Or with npm:

pnpm install -g @tomasko/mb

Or with the MoonBit toolchain, which builds from source into ~/.moon/bin:

moon install kupas/mb/cmd/mb

The installer and the npm package download the prebuilt binary from GitHub Releases for the current platform. See Build to compile from source.

Build

moon build --target native --release
# binary: _build/native/release/build/cmd/mb/mb.exe

Usage

mb run [--moon <version>] <command> [args...]
mb moon list | install [version] | uninstall <version> | default <version> | which [version] | latest
mb tool install <author>/<module>[@<version>] [--force] [--bin-dir <dir>] [--moon <version>]
mb tool list [--outdated] | upgrade [--all] <name>... | uninstall [--all] <name>...
mb env set <KEY>=<VALUE> [--global] [--plain] | rm [--global] <KEY>... | list [--global]
mb help | version

Every command and subcommand also understands -h/--help (which wins over any other argument, as in uv). --bin <dir> is accepted as an alias for --bin-dir <dir>.

Toolchains

mb moon install              # install the latest release
mb moon install 0.10.14      # install the release with moonc 0.10.14
mb moon install nightly      # install the nightly build
mb moon list                 # installed toolchains + the release channel
mb moon default 0.10.14      # select the version ~/.local/bin points at
mb moon which                # print the active moon binary
mb moon uninstall 0.10.14    # remove a toolchain and its ~/.local/bin shims

mb moon list lists the installed toolchains, then the versions published on the release channel (cli.moonbitlang.com/version.json, i.e. what latest resolves to).

Toolchains live under $MB_HOME/moon/<version> and the moon, moonc, moonfmt, ... binaries are symlinked into ~/.local/bin. Uninstalling a toolchain removes those symlinks too (it matches them by target, so nothing is left dangling), and re-points them at another installed toolchain when one is available.

Toolchains live under $MB_HOME/moon/<version> and the moon, moonc, moonfmt, ... binaries are symlinked into ~/.local/bin. Installing a toolchain also downloads and bundles core so that builds work offline.

mb moon install 0.10.14 resolves a bare compiler version to the full release key (e.g. 0.10.14+7d59c7ec9). Pass the full X.Y.Z+hash string to pin an exact build.

Running

mb run moon build            # run with the default managed toolchain
mb run --moon 0.10.14 moon test
mb run --moon nightly node script.js

mb run prepends the selected toolchain's bin to PATH and points MOON_HOME at it before executing the command, and exports the dotenv files described below. When no managed toolchain is selected it falls back to the moon already on PATH.

Environment variables

mb env set API_KEY=secret         # encrypted, stored in ./.env
mb env set GREETING "hello world" --plain
mb env set --global GITHUB_TOKEN=ghp_xxx
mb env list                       # clear values on a terminal, masked otherwise
mb env list --mask                # always mask encrypted values
mb env list --global
mb env rm API_KEY

mb env manages the dotenv files that mb run loads:

  • project (default): ./.env, with ./.mbenv also loaded when present;
  • global (--global/-g): $HOME/.mbenv, which additionally stores the encryption key.

Values are encrypted by default and written as KEY=ENC[<hex>]; the keys stay in plaintext, so listing never needs the key. mb env list reveals values only when stdout is a terminal, so a piped or captured listing shows <encrypted> instead; --mask forces masking. --plain stores a value verbatim, so an ordinary hand-written .env keeps working and plain and encrypted values can be mixed.

This TTY check is best-effort only: mb run must decrypt to hand variables to the child process, and the key lives in $HOME/.mbenv, so a process with shell access can still recover values (for example via mb run printenv). Treat the encryption as protection at rest (git, sync, backups), not as a boundary against another process running as you.

Encryption is ChaCha20 + HMAC-SHA256 in encrypt-then-MAC order (moonbitlang/x/crypto ships no AEAD): a random 96-bit nonce per value and two subkeys derived from the master key with HMAC-SHA256. The tag is verified before decryption, so a wrong key or a tampered value is rejected.

The first time a value has to be encrypted, mb env set prompts for a key and stores it in $HOME/.mbenv as a # mb-env-key: <key> directive. Set MB_ENV_KEY to override it (useful in CI); using the same value on another machine reads the same files.

mb run loads $HOME/.mbenv, then ./.mbenv, then ./.env (later files win) and exports the result before running the command. MoonBit programs can do the same with the single public entry point load_dotenv().

Tools

mb tool install bobzhang/zip         # a mooncakes.io module, latest version
mb tool install bobzhang/zip@0.1.1   # pinned version
mb tool install denoland/deno        # any GitHub repository with releases
mb tool install denoland/deno@2.9.7  # pinned to a release tag
mb tool install https://github.com/BurntSushi/ripgrep
mb tool install author/tool --moon 0.10.14 --bin-dir ~/.local/bin
mb tool install author/tool -i       # choose which executables to install
mb tool ls                           # `ls` aliases `list`
mb tool list --outdated
mb tool upgrade author/tool          # one or more names, or --all
mb tool rm author/tool               # `rm`/`remove` alias `uninstall`

Every subcommand accepts short aliases (install/add/i, upgrade/update/up, list/ls, uninstall/remove/rm, and list/ls for mb env and mb moon).

mb tool install resolves the name on mooncakes.io first. When the name is a registered module it prefers a prebuilt binary from the module's GitHub release and only compiles from source when there is none:

  1. fetch mooncakes.io/api/v0/manifest/<author>/<module> to get the version, checksum and metadata.repository;
  2. if the repository is on GitHub, look for a release asset that matches the host OS and CPU architecture. A pinned version is matched against the v<version> and <version> tags; without a pin the repository's latest release is used. Assets that are archives (zip, tar, tar.gz/tgz, tar.xz/txz, tar.bz2, tar.zst, bare gz/xz/bz2/zst, ...) are unpacked and every executable inside is installed; a plain asset is installed under a name derived from its filename (so mb-linux-x86_64 becomes mb). GitHub's sha256 digest is verified when present;
  3. otherwise fall back to building from source: download https://download.mooncakes.io/user/<author>/<module>/<version>.zip, verify its SHA-256 against the registry checksum, extract it to $MB_HOME/tool/<author>-<module>/<version>/src and run moon build --target native --release with a managed (or system) toolchain;
  4. copy every executable into $MB_HOME/tool/<author>-<module>/<version>/bin and create a symlink to it in ~/.local/bin (or the --bin-dir <dir> given), the way uv exposes tool executables.

Executables are never clobbered silently: if a target name already exists in the bin directory (whether an unrelated file or another tool's symlink), mb tool install fails with executable already exists: <name> (use --force to overwrite) and exits 2, matching uv. Pass --force to replace it.

With -i/--interactive, a tool that publishes several executables prompts with a checkbox list instead of installing all of them: space toggles, up/down (or j/k) move, a toggles everything, enter confirms and esc cancels the installation. -i needs a real terminal; a non-interactive invocation reports the candidate names instead of guessing.

Because the bin directory only holds symlinks into $MB_HOME/tool/..., the link target decides ownership: mb tool uninstall removes a link only when it still points into that tool version's directory, so a name that was taken over by another tool is left untouched. Upgrading just repoints the symlink.

A name that is not on mooncakes.io is treated as a GitHub repository — owner/repo, owner/repo@tag or a full URL — and installed from its releases the same way. It is recorded under the repository slug and the release tag.

mb tool list prints the tools directory ($MB_HOME/tool), and for each tool the directory its binaries were installed into and any that are missing. With --outdated it checks for a newer version: a mooncakes.io module is looked up in the registry, and a GitHub-only tool (one that is not a registered module) is checked against its repository's latest release. mb tool uninstall removes the symlinks from that same directory, so a tool installed with --bin <dir>/ --bin-dir <dir> is cleaned up correctly too.

mb tool upgrade takes one or more names (a version specifier is ignored and the latest version is installed) or --all for every installed tool; it always rebuilds each tool into the directory it was originally installed into. As in uv, an upgrade or uninstall without any name and without --all is a usage error.

Environment

Variable Meaning Default
MB_HOME Data directory for toolchains and tools ~/.local/share/mb
MB_BIN_DIR Where executables are installed ~/.local/bin
XDG_DATA_HOME Used when MB_HOME is unset ~/.local/share
MB_ENV_KEY Encryption key for .env values ~/.mbenv directive
GITHUB_TOKEN GitHub API token for release lookups (also GH_TOKEN) unset

Layout

$MB_HOME/
  moon/<version>/          # a full MoonBit toolchain (bin, lib, lib/core)
  moon/.default            # the selected version
  tool/<author>-<name>/<version>/
    src/                   # extracted mooncakes source
    bin/                   # the installed executables
    tool.json              # { name, version, bins, bin }

~/.local/bin/<name>        # symlink -> $MB_HOME/tool/.../bin/<name>

./.env                     # project env (values encrypted)
./.mbenv                   # optional second project env file
~/.mbenv                   # global env + the `# mb-env-key:` directive

Releases, CI and npm

  • .github/workflows/ci.yml runs moon check, moon test and a native release build on Linux and macOS.

  • .github/workflows/release.yml builds mb for linux-x86_64, linux-aarch64 and darwin-aarch64 and attaches the binaries (plus .sha256 checksums) to a GitHub Release when a v* tag is pushed:

    git tag v0.2.1 && git push origin v0.2.1
  • npmjs/ is an npm wrapper. pnpm install -g @tomasko/mb downloads the matching release asset and exposes the mb command. It is published separately to npm:

    cd npmjs && npm publish --access public
  • install.sh is the curl | bash installer:

    curl -LsSf https://raw.githubusercontent.com/tomasky/mb/main/install.sh | bash

    It detects the platform, downloads mb-<target> (plus its .sha256) from the latest release and installs it into ~/.local/bin. Options: --version <v>, --install-dir <dir>, --no-verify; environment: MB_VERSION, MB_INSTALL_DIR, MB_REPO, MB_DOWNLOAD_BASE.

    Publishing to mooncakes.io ignores npmjs/: .moonignore at the repository root excludes it (and build/editor junk) from the package that moon publish uploads.

Development

moon check          # type-check
moon test           # run the test suite
moon info && moon fmt

About

A MoonBit-native take on uv, fast toolchain and package manager for MoonBit

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages