moonbit-agent-guide

2
0
Source

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.

Install

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

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

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.

You might also like

flutter-development

aj-geddes

Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design.

643969

drawio-diagrams-enhanced

jgtolentino

Create professional draw.io (diagrams.net) diagrams in XML format (.drawio files) with integrated PMP/PMBOK methodologies, extensive visual asset libraries, and industry-standard professional templates. Use this skill when users ask to create flowcharts, swimlane diagrams, cross-functional flowcharts, org charts, network diagrams, UML diagrams, BPMN, project management diagrams (WBS, Gantt, PERT, RACI), risk matrices, stakeholder maps, or any other visual diagram in draw.io format. This skill includes access to custom shape libraries for icons, clipart, and professional symbols.

591705

ui-ux-pro-max

nextlevelbuilder

"UI/UX design intelligence. 50 styles, 21 palettes, 50 font pairings, 20 charts, 8 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, mobile app, .html, .tsx, .vue, .svelte. Elements: button, modal, navbar, sidebar, card, table, form, chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, flat design. Topics: color palette, accessibility, animation, layout, typography, font pairing, spacing, hover, shadow, gradient."

318398

godot

bfollington

This skill should be used when working on Godot Engine projects. It provides specialized knowledge of Godot's file formats (.gd, .tscn, .tres), architecture patterns (component-based, signal-driven, resource-based), common pitfalls, validation tools, code templates, and CLI workflows. The `godot` command is available for running the game, validating scripts, importing resources, and exporting builds. Use this skill for tasks involving Godot game development, debugging scene/resource files, implementing game systems, or creating new Godot components.

339397

nano-banana-pro

garg-aayush

Generate and edit images using Google's Nano Banana Pro (Gemini 3 Pro Image) API. Use when the user asks to generate, create, edit, modify, change, alter, or update images. Also use when user references an existing image file and asks to modify it in any way (e.g., "modify this image", "change the background", "replace X with Y"). Supports both text-to-image generation and image-to-image editing with configurable resolution (1K default, 2K, or 4K for high resolution). DO NOT read the image file first - use this skill directly with the --input-image parameter.

451339

fastapi-templates

wshobson

Create production-ready FastAPI projects with async patterns, dependency injection, and comprehensive error handling. Use when building new FastAPI applications or setting up backend API projects.

304231

Stay ahead of the MCP ecosystem

Get weekly updates on new skills and servers.