MoonBit's Skill Market Ships Pre-Built Wasm Binaries, Not Source Packages
Hello everyone, I am Chen Suiyi, the Tiger of Frontend. My public account is 陈随易, and my personal website is: https://chensuiyi.me.
While researching the MoonBit ecosystem recently, I found something very interesting: skills.mooncakes.io.
This thing is not a blog, nor an app store, but MoonBit's skill market.
To put it in one sentence: You write a MoonBit package, throw it onto mooncakes.io, and others can run it with a single command, without worrying about what dependencies, operating system, or compilation steps you used.
Today, let's use a few real-world examples to talk about exactly how to write one, how to use one, what it's good for, and what's truly new compared to traditional package management.
What is it? An example
Suppose I wrote a small utility with a simple function: sorting the fields in a JSON file alphabetically.
In the past, if I wanted to share this tool with others, I usually had to go through this hassle:
- Send the source code.
- Tell them how to install dependencies.
- Teach them how to compile.
- Then help them solve various environment errors.
Honestly, it's quite a hassle.
What skills.mooncakes.io does is this: you upload a MoonBit module that supports the Wasm backend, and the platform automatically builds it into a Wasm binary optimized by wasm-opt. Others only need a single command:
moon runwasm your-username/[email protected] < input.json
It just runs. No need to install Node, Python, or other environments, as long as you have the MoonBit toolchain.
Simply put, it turns code directly into executable capability.
What can it do? A few real examples
skills.mooncakes.io already has some directly runnable skills, such as:
Yoorkin/cowsay: Generates a cowsay pattern in the terminal.moonbit-community/embed: Embeds static files into MoonBit source files.moonbit-community/moongrep: A structured MoonBit code search tool.moonbitlang/yacc: An LR(1) parser generator.moonbitlang/parser/cmd/moonfmt: A MoonBit code formatter.
These functions themselves are not complex, but previously, using them often required installing various different tools, dependencies, and environments.
Now, a unified command can run them all:
moon runwasm author-name/package-name@version-number
For example:
moon runwasm Yoorkin/[email protected] -- hello
moon runwasm moonbit-community/[email protected] ./fixtures -o fixtures_bundle.mbt
moon runwasm moonbit-community/[email protected] -- scan --rules path/to/rules path/to/src
moon runwasm moonbitlang/[email protected] -- --help
moon runwasm moonbitlang/parser/cmd/[email protected]
Each skill is independent, executable, and reusable.
What does a skill project look like?
Talk is cheap, let's look directly at a minimal project.
Assume the project is called json-sort/, with the following directory structure:
json-sort/
├── moon.mod
├── moon.pkg
├── main.mbt
└── SKILL.md
moon.mod is the module configuration file, using MoonBit's own DSL format:
name = "your-username/json-sort"
version = "0.1.0"
preferred_target = "wasm"
supported_targets = "wasm"
import {
"moonbit-community/[email protected]",
}
Note the difference between the two target fields:
preferred_target only sets the default backend for commands like moon build and moon check, representing a development preference.
supported_targets is what actually restricts which backends the module supports; omitting it means all backends are supported by default.
If both the module and the package declare targets, the final supported range is the intersection of the two.
Only if the valid range includes wasm will mooncakes.io attempt to build a Wasm binary for this package, and moon runwasm can run it.
moon.pkg declares that this is an executable package, states it only supports the Wasm backend, and imports the needed dependencies:
import {
"moonbit-community/miniio",
}
options(
"is-main": true,
"supported-targets": "wasm",
)
main.mbt is the entry file, reading JSON from standard input, sorting the fields, and outputting the result:
fn main {
// Read JSON from standard input
// Sort fields alphabetically
// Output the result
}
SKILL.md is the key file. It explains what this skill is, how to invoke it, and what scenarios it suits. The platform identifies and displays your skill based on this file.
For example:
name: your-username/json-sort
description: Reads a JSON file, sorts its fields alphabetically, and outputs the result.
json-sort
Used for organizing the field order of JSON files, facilitating code review and version control.
Usage
moon runwasm your-username/[email protected] < input.json
Example
Input:
{ "b": 2, "a": 1 }
Output:
{ "a": 1, "b": 2 }
After writing it, use moon publish to upload the module to mooncakes.io.
The platform will automatically detect SKILL.md and display it on skills.mooncakes.io.
Others don't need to know where your source code is, nor do they need to compile it manually. They just need to run:
moon runwasm your-username/[email protected] < input.json
to see the result.
How to publish? How to run?
Publish
The steps are not complicated:
- Write a MoonBit module.
- Add a
SKILL.mdto the project. - Ensure the executable package declares
"is-main": true, and that the effectively supported backends includewasm(either by explicitly declaring it viasupported_targets, or by defaulting to all backends and ensuring the code actually compiles under Wasm). - Execute
moon publishto upload the module to mooncakes.io. - The platform will automatically build Wasm for packages supporting the Wasm backend, optimize it with wasm-opt, and then display it on
skills.mooncakes.io.
The whole process doesn't require you to manually compile Wasm or write complex release scripts. After uploading, the platform handles it automatically.
Run
moon runwasm is currently an experimental command. After publishing, others only need one command:
moon runwasm username/package-name[@version-number] [arguments]
The version number can be omitted; when omitted, the latest version is resolved from the registry (already downloaded ones will preferentially use the local cache). For example:
moon runwasm Yoorkin/cowsay -- hello
moon runwasm Yoorkin/[email protected] -- hello
If a module has multiple executable sub-packages, you can specify the entry point via the package path. The @version-number can be placed after the module name or after the full package path; both syntaxes are equivalent:
moon runwasm moonbitlang/parser/cmd/[email protected]
moon runwasm moonbitlang/[email protected]/cmd/moonfmt
When passing arguments to the Wasm program, it is recommended to use -- to separate moon runwasm's options from the arguments to be passed to the program:
moon runwasm Yoorkin/cowsay -- hello world
This is completely different from installing Python packages or Node packages. No virtual environment is needed, no dependency installation is required, and it won't pollute the system.
Comparison with traditional methods
Suppose you want to use a certain JavaScript tool. The traditional process might be:
npm install -g some-tool
# or npx some-tool
# or clone repo -> npm install -> npm run build
During this process, you will likely encounter: version conflicts, global pollution, incompatible Node versions, dependency installation failures, network issues, and so on.
With MoonBit Skills, you only need:
moon runwasm author/package@version
Just this one line.
What problems does it solve?
Let's look directly at a few scenarios.
Ad-hoc tools
You temporarily want to do something in the terminal, like generating a cowsay pattern:
moon runwasm Yoorkin/[email protected] -- hello
Use it and leave, no installation, no system pollution.
CI/CD scripts
A build process needs a specific text processing tool. The traditional way might involve pulling a Docker image or configuring a specific language environment. With MoonBit Skills, it's just one command, saving trouble.
AI Agent tool invocation
Future AI Agents might call a large number of tools. If each tool can be packaged into an interpretable, executable, distributable skill unit, the Agent can directly read SKILL.md to know what it is, how to call it, and then execute it.
Cross-team collaboration
You wrote an internal formatting tool and want to give it to a colleague. Previously, you had to send documentation, configure environments, and teach installation. Now, just give your colleague one command:
moon runwasm your-username/[email protected]
and they can use it directly.
Summary
The problems it solves are roughly these:
- Publishing tools is troublesome.
- Environment dependencies are complex.
- Execution is uncontrollable.
- Cross-platform compatibility is poor.
- Discoverability is poor.
- Executability is poor.
In one sentence: It makes capability as easy to share and invoke as a URL.
What's new compared to traditional package management?
Some might ask: Isn't this what npm, cargo, pip do?
The difference is actually quite significant. Let me list a comparison table:
| Feature | Traditional Language Package Management | MoonBit Skills |
|---|---|---|
| Distribution Object | Source code package + dependency declaration | Pre-built Wasm binary |
| Dependency Isolation | Has a dependency tree, often has version conflicts | Skills are independent of each other, no dependency tree |
| Sandbox Isolation | Scripts can execute arbitrary code | Wasm sandbox isolation |
| Self-description | README format is not unified | Standard SKILL.md, directly understandable by Agents |
Turning packages into skills
Some might say: npx is also a one-line command.
But npx runs a source code package, which still needs to resolve the dependency tree, handle version conflicts, and possibly run postinstall scripts behind the scenes. MoonBit Skills runs a Wasm binary that the platform has already built. No node_modules, no version conflicts, and no lifecycle scripts.
Traditional package management manages dependencies; you install a package and still have to write code to use it. MoonBit Skills manages capabilities; find a skill, and you can execute it directly.
Simply put, traditional package management is like giving someone a pile of parts; MoonBit Skills gives you a finished product directly.
Wasm as the default execution format
In many language ecosystems, Wasm is just an optional target, but in MoonBit Skills, Wasm is the default distribution form.
Choosing Wasm as the distribution format was not arbitrary. It has several advantages that are particularly suited to the skill scenario:
- Cross-platform consistency: The same Wasm binary behaves consistently on Windows, macOS, and Linux, without needing to package separately for different systems.
- Sandbox isolation: Wasm runs in a restricted environment and by default cannot arbitrarily access the file system or network, making it safer than running scripts directly.
- Dependency-free, independent execution: A skill is a single binary, without a dependency tree like
node_modules, and won't conflict with other tools on the system. - Fast startup, small size: After wasm-opt optimization, the binary is small in size and has fast cold starts, making it very suitable for CI/CD and Agent tool invocation.
This is why MoonBit Skills can achieve: write a tool, upload it, and others can run it directly with one command.
SKILL.md as a capability description standard
This design is quite interesting.
SKILL.md uses structured frontmatter (name, description) plus Markdown body to unify the description method for skills.
In the future, when AI Agents need to call tools, they won't have to guess how your API works; reading SKILL.md tells them the command format and scenario.
Language-level toolchain integration
moon runwasm is a command natively supported by the MoonBit toolchain, not a third-party plugin.
The entire chain from writing code to publishing a skill to being run by others is natively connected.
What does it mean for developers?
- The tools you write are no longer just your own scripts, but capabilities that can be directly run by the whole world.
- No need to write complex installation documentation; one command lets others use it.
- No need to package for different platforms; Wasm solves the cross-platform problem for you.
- Your capabilities are more easily discovered and called by AI Agents and other tools.
What does it mean for ordinary users?
- See a tool, no need to study the source code, no need to configure the environment, one command to try it.
- Doesn't pollute the system, doesn't install global dependencies.
- Use it and leave, as natural as calling a local command.
Conclusion
skills.mooncakes.io is a quite interesting attempt within the MoonBit ecosystem.
It's not just about making packages easier to publish, but about making capabilities easier to share, discover, and invoke.
The core idea is three sentences:
- Write a tool once.
- Upload it as a skill.
- Others can run it with one command.
It's not distributing libraries, it's distributing capabilities.
Honestly, I personally am quite optimistic about this direction.
Especially as AI Agents become more and more popular, the value of this kind of write it, run it, discard it capability unit will only grow.
I wonder what you think? Welcome to leave a comment in the comment section.