From moonbit-practice
Provides MoonBit best practices for code generation, navigation with moon ide/doc, and fixes for common AI syntax pitfalls like type params, raise, macros, and loops.
npx claudepluginhub mizchi/moonbit-practice --plugin moonbit-practiceThis skill uses the workspace's default tool permissions.
Best practices for AI when generating MoonBit code.
Applies Acme Corporation brand guidelines including colors, fonts, layouts, and messaging to generated PowerPoint, Excel, and PDF documents.
Builds DCF models with sensitivity analysis, Monte Carlo simulations, and scenario planning for investment valuation and risk assessment.
Calculates profitability (ROE, margins), liquidity (current ratio), leverage, efficiency, and valuation (P/E, EV/EBITDA) ratios from financial statements in CSV, JSON, text, or Excel for investment analysis.
Best practices for AI when generating MoonBit code.
If you don't understand something here, use moonbit-docs skill to search the official documentation.
In MoonBit projects, prefer moon ide commands over Read tool or grep.
# ❌ Avoid: Reading files directly
Read src/parser.mbt
# ✅ Recommended: Find definitions from symbols
moon ide peek-def Parser::parse
moon ide goto-definition -tags 'pub fn' -query 'parse'
# ❌ Avoid: Searching with grep
grep -r "fn parse" .
# ✅ Recommended: Semantic search
moon ide find-references parse
moon ide outline src/parser.mbt
Why:
moon ide provides semantic search (distinguishes definitions from call sites)moon doc quickly reveals APIsmoon doc '<Type>' to explore APIs before implementingmut is only for reassignment, not field mutation - Array push doesn't need itreturn is unnecessary - last expression is the return valueType:: prefix++ -- not supported - use i = i + 1 or i += 1try needed for error propagation - automatic (unlike Swift)await keyword - just declare with async fnfor i in 0..<n {...}nobreak not else for functional for-loop exit values (else is deprecated)function_name!(...) and function_name(...)? are deprecatedfor { ... } is deprecated - use for ;; { ... } or while true { ... } for infinite loops. syntax for impl removed - . method call only works within the same package///| NG: fn identity[T] is old syntax
fn identity[T](val: T) -> T { val }
///| OK: Type parameter comes right after fn
fn[T] identity(val: T) -> T { val }
///|
/// NG: -> T!Error was removed
fn parse(s: String) -> Int!Error { ... }
///|
/// OK: Use raise keyword
fn parse(s: String) -> Int raise Error { ... }
Int raise is shorthand for Int raise Error.
async fn implicitly raises by default; use noraise to enforce no errors.
///|
/// NG: ! suffix was removed
assert_true!(true)
///|
/// OK
assert_true(true)
let text =
#|line 1
#|line 2
///| is a block separator. /// comments attach to the following ///| block.
///|
/// This function is foo
fn foo() -> Unit { ... }
///|
/// This function is bar
fn bar() -> Unit { ... }
Avoid consecutive ///| at the file beginning as they create separate blocks.
moon test -u auto-updates content="" in inspect(val).
test "snapshot" {
inspect([1, 2, 3], content="") // auto-filled by moon test -u
}
After running:
test "snapshot" {
inspect([1, 2, 3], content="[1, 2, 3]")
}
Available in .mbt.md files or ///| inline comments.
| Code Block | Behavior |
|---|---|
```mbt check | Checked by LSP |
```mbt test | Executed as test {...} |
```moonbit | Display only (not executed) |
Example (inline comment):
///|
/// Increment an integer by 1
/// ```mbt test
/// inspect(incr(41), content="42")
/// ```
pub fn incr(x : Int) -> Int {
x + 1
}
Run before releasing:
moon fmt # Format code
moon info # Generate type definition files
pkg.generated.mbti is auto-generated by moon info. Don't edit it directly.
moon doc StringView # StringView methods
moon doc Array # Array methods
moon doc Map # Map methods
| Topic | Command | Details |
|---|---|---|
| Test | moon test | https://docs.moonbitlang.com/en/stable/language/tests |
| Update snapshots | moon test -u | Same as above |
| Filtered test | moon test --filter 'glob' | Run specific tests |
| Benchmark | moon bench | https://docs.moonbitlang.com/en/stable/language/benchmarks |
| Doc Test | moon check / moon test | https://docs.moonbitlang.com/en/stable/language/docs |
| Format | moon fmt | - |
| Generate types | moon info | - |
| Doc reference | moon doc <Type> | - |
| Workspace init | moon work init | See reference/configuration.md |
| Workspace add | moon work use mod1 mod2 | Add modules to workspace |
| API usage analysis | moon ide analyze . | Show public API usage stats |
More accurate than grep for code navigation. See reference/ide.md for details.
# Show symbol definition
moon ide peek-def Parser::read_u32_leb128
# Package outline
moon ide outline .
# Find references
moon ide find-references TranslationUnit
# Jump to type definition (with location)
moon ide peek-def Parser -loc src/parse.mbt:46:4
# Show type signature and docs at location (unlike peek-def, shows inferred type + doc comments)
moon ide hover my_func --loc src/lib.mbt:10:4
# Rename symbol across the project
moon ide rename old_name new_name
# Analyze public API usage (v0.8.3+)
moon ide analyze . # Current package
moon ide analyze internal/* # Glob pattern
Prefer functional for loops whenever possible. More readable and easier to reason about.
// Functional for loop with state
for i = 0, sum = 0; i <= 10 {
continue i + 1, sum + i // Update state
} nobreak {
sum // Value at loop exit (nobreak, not else)
}
// Range for (recommended)
for i in 0..<n { ... }
for i, v in array { ... } // index and value
// Range for with extra loop variable (v0.8.3+)
for x in xs; sum = 0 {
continue sum + x
} nobreak {
sum
}
// Infinite loop (for { } is deprecated)
for ;; { ... }
const supports string concatenation and interpolation (v0.8.3+):
const Hello : String = "Hello"
const HelloWorld : String = Hello + " world"
const Message : String =
$|========
$|\{HelloWorld}
$|========
MoonBit uses checked errors. See reference/ffi.md for details.
///| Declare error type
suberror ParseError {
InvalidEof
InvalidChar(Char)
}
///| Declare with raise, auto-propagates
fn parse(s: String) -> Int raise ParseError {
if s.is_empty() { raise ParseError::InvalidEof }
...
}
///| Convert to Result
let result : Result[Int, ParseError] = try? parse(s)
///| Handle with try-catch
parse(s) catch {
ParseError::InvalidEof => -1
_ => 0
}
moonbit-community/moonbit-overlay provides a Nix flake overlay for reproducible MoonBit builds.
Minimal flake.nix for a MoonBit project:
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
moonbit-overlay.url = "github:moonbit-community/moonbit-overlay";
moon-registry = {
url = "git+https://mooncakes.io/git/index";
flake = false;
};
};
outputs = { nixpkgs, moonbit-overlay, moon-registry, ... }:
let
system = "x86_64-linux"; # or aarch64-darwin, etc.
pkgs = import nixpkgs {
inherit system;
overlays = [ moonbit-overlay.overlays.default ];
};
moonHome = pkgs.moonPlatform.bundleWithRegistry {
cachedRegistry = pkgs.moonPlatform.buildCachedRegistry {
moonModJson = ./moon.mod.json;
registryIndexSrc = moon-registry;
};
};
in {
devShells.${system}.default = pkgs.mkShellNoCC {
packages = [ moonHome pkgs.git ];
env.MOON_HOME = "${moonHome}";
};
};
}
Key APIs from the overlay:
pkgs.moonPlatform.buildMoonPackage - Build a MoonBit package as a Nix derivationpkgs.moonPlatform.bundleWithRegistry - Create a MOON_HOME with cached registrypkgs.moonPlatform.buildCachedRegistry - Pre-fetch mooncakes registry dependencies