MO

moonbit-agent-guide

Helps users build MoonBit packages, manage metadata, and execute tests following standard project structures.

Install

mkdir -p .claude/skills/moonbit-agent-guide && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/3295" && unzip -o skill.zip -d .claude/skills/moonbit-agent-guide && rm skill.zip

Installs to .claude/skills/moonbit-agent-guide

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Guide for writing, refactoring, and testing MoonBit projects. Use when working in MoonBit modules or packages, organizing MoonBit files, using moon tooling (build/check/test/doc/ide), or following MoonBit-specific layout, documentation, and testing conventions.
261 chars✓ has a “when” triggerlonger than Claude Code's old 250-char listing cap (fine on current versions)
Intermediate

Key capabilities

  • Assists with creating MoonBit modules and packages
  • Enforces standard project layouts and file organization
  • Provides commands for building, checking, and testing code
  • Supports snapshot testing and coverage analysis
  • Generates interface files for public API surface overview

How it works

The skill guides users through MoonBit-specific conventions, enforcing strict layout rules and providing essential CLI commands for project management.

Inputs & outputs

You give it
MoonBit project file or command request
You get back
Refactored code, test results, or build artifacts

When to use moonbit-agent-guide

  • Create new MoonBit modules
  • Organize code into mbt packages
  • Run internal white-box tests
  • Execute MoonBit builds and checks

About this skill

MoonBit Project Layouts

MoonBit use the .mbt extension and interface files .mbti. At the top-level of a MoonBit project there is a moon.mod.json file specifying the metadata of the project. The project may contain multiple packages, each with its own moon.pkg.json file.

Example layout

my_module
├── moon.mod.json             # Module metadata, source field(optional) specifies the source directory of the module
├── moon.pkg.json             # Package metadata (each directory is a package like Golang)
├── README.mbt.md             # Markdown with tested code blocks (`test "..." { ... }`)
├── README.md -> README.mbt.md
├── cmd                       # Command line directory
│   └── main
│       ├── main.mbt
│       └── moon.pkg.json     # executable package with {"is_main": true}
├── liba/                     # Library packages
│   └── moon.pkg.json         # Referenced by other packages as `@username/my_module/liba`
│   └── libb/                 # Library packages
│       └── moon.pkg.json     # Referenced by other packages as `@username/my_module/liba/libb`
├── user_pkg.mbt              # Root packages, referenced by other packages as `@username/my_module`
├── user_pkg_wbtest.mbt       # White-box tests (only needed for testing internal private members, similar to Golang's package mypackage)
└── user_pkg_test.mbt         # Black-box tests
└── ...                       # More package files, symbols visible to current package (like Golang)
  • Module: moon.mod.json file in the project directory. A MoonBit module is like a Go module,it is a collection of packages in subdirectories, usually corresponding to a repository or project. Module boundaries matter for dependency management and import paths.

  • Package: a moon.pkg.json file per directory. All subcommands of moon will still be executed in the directory of the module (where moon.mod.json is located), not the current package. A MoonBit package is the actual compilation unit (like a Go package). All source files in the same package are concatenated into one unit. The package name in the source defines the package, not the file name. Imports refer to module + package paths, NEVER to file names.

  • Files: A .mbt file is just a chunk of source inside a package. File names do NOT create modules or namespaces. You may freely split/merge/move declarations between files in the same package. Any declaration in a package can reference any other declaration in that package, regardless of file.

Coding/layout rules you MUST follow:

  1. Prefer many small, cohesive files over one large file.

    • Group related types and functions into focused files (e.g. http_client.mbt, router.mbt).
    • If a file is getting large or unfocused, create a new file and move related declarations into it.
  2. You MAY freely move declarations between files inside the same package.

    • Each block is separated by ///|, moving a function/struct/trait between files does not change semantics, as long as its name and pub-ness stay the same, the order of each block is irrelevant too.
    • It is safe to refactor by splitting or merging files inside a package.
  3. File names are purely organizational.

    • Do NOT assume file names define modules, and do NOT use file names in type paths.
    • Choose file names to describe a feature or responsibility, not to mirror type names rigidly.
  4. When adding new code:

    • Prefer adding it to an existing file that matches the feature.
    • If no good file exists, create a new file under the same package with a descriptive name.
    • Avoid creating giant “misc” or “util” files.
  5. Tests:

    • Place tests in dedicated test files (e.g. *_test.mbt) within the appropriate package. For a package, besides *_test.mbtfiles,*.mbt.mdare also blackbox test files, the code block mbt check are treated as test cases, they serve both purposes: documentation and tests.
      You may have README.mbt.md files with mbt check code examples, you can also symlink README.mbt.md to README.md to make it integrate better with GitHub.
    • It is fine—and encouraged—to have multiple small test files.
  6. Interface files(pkg.generated.mbti) pkg.generated.mbti is compiler-generated summaries of each package's public API surface. They provide a formal, concise overview of all exported types, functions, and traits without implementation details. They are generated using moon info, useful for code review, when you have a commit that does not change public APIs, pkg.generated.mbti files will remain unchanged, so it is recommended to put pkg.generated.mbti in version control when you are done.

    You can also use moon doc @moonbitlang/core/strconv to explore the public API of a package interactively and moon ide peek-def 'Array::join' to read the definition.

Common Pitfalls to Avoid

  • Don't use uppercase for variables/functions - compilation error
  • Don't forget mut for mutable record fields - immutable by default
  • Don't ignore error handling - errors must be explicitly handled
  • Don't use return unnecessarily - last expression is the return value
  • Don't create methods without Type:: prefix - methods need explicit type prefix
  • Don't forget to handle array bounds - use get() for safe access
  • Don't forget @package prefix when calling functions from other packages
  • Don't use ++ or -- (not supported) - use i = i + 1 or i += 1
  • Don't add explicit try for error-raising functions - errors propagate automatically (unlike Swift)
  • Legacy syntax: Older code may use function_name!(...) or function_name(...)? - these are deprecated; use normal calls and try? for Result conversion

moon Essentials

Essential Commands

  • moon new my_project - Create new project
  • moon run cmd/main - Run main package
  • moon build - Build project
  • moon check - Type check without building, use it REGULARLY, it is fast
  • moon info - Type check and generate mbti files run it to see if any public interfaces changed.
  • moon check --target all - Type check for all backends
  • moon add package - Add dependency
  • moon remove package - Remove dependency
  • moon fmt - Format code

Test Commands

  • moon test - Run all tests
  • moon test --update - Update snapshots
  • moon test -v - Verbose output with test names
  • moon test [dirname|filename] - Test specific directory or file
  • moon coverage analyze - Analyze coverage
  • moon test --filter 'globl' - Run tests matching filter
    moon test float/float_test.mbt --filter "Float::*"
    

README.mbt.md Generation Guide

  • Output README.mbt.md in the package directory. *.mbt.md file and docstring contents treats mbt check specially. mbt check block will be included directly as code and also run by moon check and moon test. If you don't want the code snippets to be checked, explicit mbt nocheck is preferred. If you are only referencing types from the package, you should use mbt nocheck which will only be syntax highlighted. Symlink README.mbt.md to README.md to adapt to systems that expect README.md.

Testing Guide

Use snapshot tests as it is easy to update when behavior changes.

  • Snapshot Tests: inspect(value, content="..."). If unknown, write inspect(value) and run moon test --update (or moon test -u).

    • Use regular inspect() for simple values (uses Show trait)
    • Use @json.inspect() for complex nested structures (uses ToJson trait, produces more readable output)
    • It is encouraged to inspect or @json.inspect the whole return value of a function if the whole return value is not huge, this makes test simple. You need impl (Show|ToJson) for YourType or derive (Show, ToJson).
  • Update workflow: After changing code that affects output, run moon test --update to regenerate snapshots, then review the diffs in your test files (the content= parameter will be updated automatically).

  • Black-box by default: Call only public APIs via @package.fn. Use white-box tests only when private members matter.

  • Grouping: Combine related checks in one test "..." { ... } block for speed and clarity.

  • Panics: Name test with prefix test "panic ..." {...}; if the call returns a value, wrap it with ignore(...) to silence warnings.

  • Errors: Use try? f() to get Result[...] and inspect it when a function may raise.

  • Verify: Run moon test (or -u to update snapshots) and moon fmt afterwards.

Docstring tests

Public APIs are encouraged to have docstring tests.

///|
/// Get the largest element of a non-empty `Array`.
///
/// # Example
/// ```mbt check
/// test {
///   inspect(sum_array([1, 2, 3, 4, 5, 6]), content="21")
/// }
/// ```
///
/// # Panics
/// Panics if the `xs` is empty.
pub fn sum_array(xs : Array[Int]) -> Int {
  xs.fold(init=0, (a, b) => a + b)
}

The MoonBit code in docstring will be type checked and tested automatically. (using moon test --update). In docstrings, mbt check should only contain test or async test.

Spec-driven Development

  • The spec can be written in a readonly spec.mbt file (name is conventional, not mandatory) with stub code marked as declarations:
///|
#declaration_only
pub type Yaml

///|
#declaration_only
pub fn Yaml::to_string(y : Yaml) -> String raise {
  ...
}

///|
#declaration_only
pub fn parse_yaml(s : String) -> Yaml raise {
  ...
}
  • Add spec_easy_test.mbt, spec_difficult_test.mbt etc to test the spec functions; everything will be type-checked(moon check).

  • The AI or students can implement the declaration_only functions in different files thanks to our package organization.

  • Run moon test to check everything is correct.

  • #declaration_only is supported for functions, methods, and types.

  • The pub type Yaml line is an intentionally opaque placeho


Content truncated.

When not to use it

  • When working outside of MoonBit modules or packages
  • When using deprecated syntax like function_name!

Limitations

  • Requires adherence to specific file naming and organization rules
  • Strict syntax requirements for variables and functions

How it compares

It provides specialized guidance on MoonBit's unique module/package structure and testing workflows that differ from general-purpose languages.

Compared to similar skills

moonbit-agent-guide side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
moonbit-agent-guide (this skill)16moReviewIntermediate
code-assist15moNo flagsAdvanced
ruby-pro14moNo flagsAdvanced
agent-implementer-sparc-coder16moReviewIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

Search skills

Search the agent skills registry