admiral

Async-first declarative CLI builder for MoonBit, inspired by gunshi

cli
argparse
moonbit
Download zip
Author
Version
0.6.5
License
MIT
Last updated
19 hours ago
Downloads
366

#admiral

Admiral is an async-first declarative CLI module for MoonBit applications that need typed arguments, configuration, interactive input, schema output, and shell completion.

#Usage

Build a greeter that passes a required name to its callback. The checked typed-option example verifies that --name Alice produces the captured "Alice" value.

Use a nested command when it owns an option such as a server port. The checked nested-command example verifies that MYAPP_PORT=8080 reaches the serve callback as an Int.

For filesystem discovery, the checked target-file-discovery Usage example creates a temporary project.toml and verifies that the helper returns its exact path.

#Key features

  • Typed declarative CLI definitions, async command execution, configuration, interactive input, schema rendering, and completion.
  • Cross-target asynchronous discovery of named files with inherited .gitignore rules.
  • JavaScript, native, and Wasm module targets, with JavaScript as the preferred target.

#Prerequisites

  • MoonBit: Install the MoonBit toolchain.
  • Supported targets: Use JavaScript, native, or Wasm according to the consuming application.

#Setup

moon add totto2727/admiral moon add moonbitlang/async

Import the CLI package in a consuming package's moon.pkg. This package supports JavaScript and native targets:

supported_targets = "js+native" import { "totto2727/admiral" @admiral, "moonbitlang/async", }

Import the target-file discovery package from the same module instead when the application needs its JavaScript, native, and Wasm-compatible filesystem helpers:

supported_targets = "js+native+wasm" import { "totto2727/admiral/util/target-file-discovery" @target-file-discovery, "moonbitlang/async", }

For the distinct filesystem helper API, see target-file-discovery.

#API

The Mooncakes Admiral API reference is the canonical generated API index for the published CLI package. For the distinct filesystem helper API, see the target-file-discovery guide.

#Defining options and positions

Option and position constructors return typed definitions. The scalar helpers are string, bool, int, int64, uint, uint64, and double; each has a repeated form such as strings or doubles. Position helpers provide the same scalar and repeated numeric families.

Pass the same definition to CommandDef::CommandDef or CliApp::CliApp and to the matching Context getter so the option name remains one type-checked source of truth.

The checked typed-definition example verifies option metadata and a required positional definition.

#Reading values

Context exposes scalar getters such as get_bool, get_string, get_int, get_int64, get_uint, get_uint64, and get_double, plus raising _required variants. Repeated values use get_strings, get_ints, get_int64s, get_uints, get_uint64s, and get_doubles; their _required variants return NonEmptyArray and raise when no value is available.

#Environment and configuration

CliApp::run reads process arguments and environment by default, while tests and embedders can inject both sources. Values resolve in the order argv > env > config > default.

Environment-backed booleans accept 1, 0, true, false, yes, no, on, and off; the parsing and precedence rules come from moonbitlang/core/argparse.

Provide load_config when configuration must come from a file or another source. It returns a Map[String, Json], and its keys are the independent config names declared on definitions.

#Nested commands and positions

Commands can contain subcommands and each command owns its options, positions, examples, and callback. Context::get_subcommand() returns the selected subcommand name and its nested context when a child command was selected.

#Interactive input

Set interactive=true on definitions and provide one callback on the owning command or application. Admiral invokes it only when an opted-in definition is present and a TTY is available. InteractiveContext::to_context() exposes initial values, and typed setters replace selected values before the command callback runs.

#Schema and completion

ToJson::to_json(app) returns the structured schema, while render_schema() returns its string form. render_bash_completion(), render_zsh_completion(), and render_fish_completion() generate shell-specific completion scripts.

The checked schema-rendering example verifies that an option name appears in the generated schema.

#Development

For development guidance, see AGENTS.md.

#License

MIT. See LICENSE.

This README was generated from the share-artifact skill and README template.

OptionDef

type OptionDef[T] = ArgDef[T, OptionMetadata]

Typed definition for an option declaration.

PositionDef

type PositionDef[T] = ArgDef[T, PositionMetadata]

Typed definition for a positional argument declaration.

ToStoredOption

trait ToStoredOption

ToStoredPosition

trait ToStoredPosition

ConfigLoadFailure

pub(all) suberror ConfigLoadFailure {
ConfigLoadFailure(String)
} derive(Eq,
Debug
)

Failure raised by a configuration loader when external configuration cannot be read or decoded into a map.

ArgDef

pub struct ArgDef[_, Metadata] {
name : String
config : String?
metadata : Metadata
} derive(
Debug
)

Typed, read-only argument definition shared by a parser declaration and its matching Context getter.

CliApp

pub struct CliApp {
name : String
version : String
description : String
root_options : Array[ArgDef[Unit, OptionMetadata]]
root_positionals : Array[ArgDef[Unit, PositionMetadata]]
commands : Array[CommandDef]
interactive : async (InteractiveContext) -> Unit?
run : async (Context) -> Unit?
load_config : () -> Map[String, Json] raise ConfigLoadFailure?
}

Root application definition containing global arguments and command routing.
impl ToJson for CliApp

CliApp::CliApp

fn CliApp::CliApp(name~ : String, version? : String, description? : String, options? : Array[&ToStoredOption], positionals? : Array[&ToStoredPosition], commands? : Array[CommandDef], interactive? : async (InteractiveContext) -> Unit?, run? : async (Context) -> Unit?, load_config? : () -> Map[String, Json] raise ConfigLoadFailure?) -> CliApp

Constructs the root CLI application. run handles root arguments, while commands dispatches nested command paths; load_config supplies a map of independent configuration keys.

CliApp::render_bash_completion

fn CliApp::render_bash_completion(self : CliApp) -> String

Renders a Bash completion function for the application's commands and options. Install the returned script in a Bash completion file.

CliApp::render_fish_completion

fn CliApp::render_fish_completion(self : CliApp) -> String

Renders Fish completion declarations for the application's commands and options. Save the returned text under Fish's completions directory.

CliApp::render_schema

fn CliApp::render_schema(self : CliApp) -> String

Renders the complete CLI definition as a JSON string for documentation and tooling integrations.

CliApp::render_zsh_completion

fn CliApp::render_zsh_completion(self : CliApp) -> String

Renders a Zsh completion function for the application's commands and options. Install the returned script in a Zsh completion file.

CliApp::run

async fn CliApp::run(self : CliApp, argv? : Array[String]?, env? : Map[String, String]) -> Unit

Parses inputs and runs the selected callback, invoking interactive input only when at least one selected definition opts in and an input TTY is available.

CommandDef

pub struct CommandDef {
name : String
description : String
options : Array[ArgDef[Unit, OptionMetadata]]
positionals : Array[ArgDef[Unit, PositionMetadata]]
examples : Array[String]
subcommands : Array[CommandDef]
interactive : async (InteractiveContext) -> Unit?
run : async (Context) -> Unit?
}

A declarative command definition with options, positions, nested commands, optional interactive input, and an async execution callback.

CommandDef::CommandDef

fn CommandDef::CommandDef(name~ : String, description? : String, options? : Array[&ToStoredOption], positionals? : Array[&ToStoredPosition], examples? : Array[String], subcommands? : Array[CommandDef], interactive? : async (InteractiveContext) -> Unit?, run? : async (Context) -> Unit?) -> CommandDef

Constructs a command definition. The same typed option or position value can be passed to the declaration and later to its matching context getter.

Context

pub struct Context {
flags :
HashMap
[String, Bool]
values :
HashMap
[String, ReadOnlyArray[String]]
sources :
HashMap
[String,
ValueSource
]
config :
HashMap
[String, Json]
interactive_flags :
HashMap
[String, Bool]
interactive_values :
HashMap
[String, ReadOnlyArray[String]]
subcommand : (String, Context)?
}

Parsed values and independently loaded configuration for a command callback.

Context::Context

fn Context::Context(flags? : Map[String, Bool], values? : Map[String, Array[String]], sources? : Map[String,
ValueSource
], config? : Map[String, Json], subcommand? : (String, Context)?) -> Context

Creates a context from parser maps and an optional configuration map. The constructor is useful for embedding or tests that provide explicit matches.

Context::get_bool

Boolean options are flags stored separately from positional values. Their absence means false, so this getter intentionally accepts only OptionDef.

Context::get_double

fn[Metadata] Context::get_double(self : Context, argument : ArgDef[Double, Metadata]) -> Double? raise

Parses and returns the first double value, or None when absent.

Context::get_double_required

fn[Metadata] Context::get_double_required(self : Context, argument : ArgDef[Double, Metadata]) -> Double raise

Returns the required double value.

Context::get_doubles

fn[Metadata] Context::get_doubles(self : Context, argument : ArgDef[Array[Double], Metadata]) -> ReadOnlyArray[Double] raise

Parses and returns all double values.

Context::get_doubles_required

fn[Metadata] Context::get_doubles_required(self : Context, argument : ArgDef[Array[Double], Metadata]) -> NonEmptyArray[Double] raise

Returns all required double values as a NonEmptyArray.

Context::get_int

fn[Metadata] Context::get_int(self : Context, argument : ArgDef[Int, Metadata]) -> Int? raise

Parses and returns the first signed integer value, or None when absent.

Context::get_int64

fn[Metadata] Context::get_int64(self : Context, argument : ArgDef[Int64, Metadata]) -> Int64? raise

Parses and returns the first 64-bit signed integer value, or None when absent.

Context::get_int64_required

fn[Metadata] Context::get_int64_required(self : Context, argument : ArgDef[Int64, Metadata]) -> Int64 raise

Returns the required 64-bit signed integer value.

Context::get_int64s

fn[Metadata] Context::get_int64s(self : Context, argument : ArgDef[Array[Int64], Metadata]) -> ReadOnlyArray[Int64] raise

Parses and returns all 64-bit signed integer values.

Context::get_int64s_required

fn[Metadata] Context::get_int64s_required(self : Context, argument : ArgDef[Array[Int64], Metadata]) -> NonEmptyArray[Int64] raise

Returns all required 64-bit signed integer values as a NonEmptyArray.

Context::get_int_required

fn[Metadata] Context::get_int_required(self : Context, argument : ArgDef[Int, Metadata]) -> Int raise

Returns the required signed integer value, raising when it is absent.

Context::get_ints

fn[Metadata] Context::get_ints(self : Context, argument : ArgDef[Array[Int], Metadata]) -> ReadOnlyArray[Int] raise

Parses and returns all signed integer values, or an empty array when absent.

Context::get_ints_required

fn[Metadata] Context::get_ints_required(self : Context, argument : ArgDef[Array[Int], Metadata]) -> NonEmptyArray[Int] raise

Returns all required signed integer values as a NonEmptyArray.

Context::get_string

fn[Metadata] Context::get_string(self : Context, argument : ArgDef[String, Metadata]) -> String? raise
JsonDecodeError

Returns the first string value from an option or positional definition, or None when the argument is absent. Configuration JSON is decoded when the parser source is a default or is missing.

Context::get_string_required

fn[Metadata] Context::get_string_required(self : Context, argument : ArgDef[String, Metadata]) -> String raise

Returns the required string value, raising when argument is absent.

Context::get_strings

fn[Metadata] Context::get_strings(self : Context, argument : ArgDef[Array[String], Metadata]) -> ReadOnlyArray[String] raise
JsonDecodeError

Returns all string values, or an empty read-only array when absent.

Context::get_strings_required

fn[Metadata] Context::get_strings_required(self : Context, argument : ArgDef[Array[String], Metadata]) -> NonEmptyArray[String] raise

Returns all required string values as a NonEmptyArray.

Context::get_subcommand

fn Context::get_subcommand(self : Context) -> (String, Context)?

Returns the selected subcommand name and its nested context, when present.

Context::get_uint

fn[Metadata] Context::get_uint(self : Context, argument : ArgDef[UInt, Metadata]) -> UInt? raise

Parses and returns the first unsigned integer value, or None when absent.

Context::get_uint64

fn[Metadata] Context::get_uint64(self : Context, argument : ArgDef[UInt64, Metadata]) -> UInt64? raise

Parses and returns the first 64-bit unsigned integer value, or None when absent.

Context::get_uint64_required

fn[Metadata] Context::get_uint64_required(self : Context, argument : ArgDef[UInt64, Metadata]) -> UInt64 raise

Returns the required 64-bit unsigned integer value.

Context::get_uint64s

fn[Metadata] Context::get_uint64s(self : Context, argument : ArgDef[Array[UInt64], Metadata]) -> ReadOnlyArray[UInt64] raise

Parses and returns all 64-bit unsigned integer values.

Context::get_uint64s_required

fn[Metadata] Context::get_uint64s_required(self : Context, argument : ArgDef[Array[UInt64], Metadata]) -> NonEmptyArray[UInt64] raise

Returns all required 64-bit unsigned integer values as a NonEmptyArray.

Context::get_uint_required

fn[Metadata] Context::get_uint_required(self : Context, argument : ArgDef[UInt, Metadata]) -> UInt raise

Returns the required unsigned integer value.

Context::get_uints

fn[Metadata] Context::get_uints(self : Context, argument : ArgDef[Array[UInt], Metadata]) -> ReadOnlyArray[UInt] raise

Parses and returns all unsigned integer values.

Context::get_uints_required

fn[Metadata] Context::get_uints_required(self : Context, argument : ArgDef[Array[UInt], Metadata]) -> NonEmptyArray[UInt] raise

Returns all required unsigned integer values as a NonEmptyArray.

InteractiveContext

pub struct InteractiveContext {
initial : Context
flags : Map[String, Bool]
values : Map[String, Array[String]]
}

Mutable input passed to an interactive callback. Values set here override parser, environment, configuration, and default values before execution. Accumulates values selected by a command's interactive input callback. Read to_context() before setting values to obtain the resolved argv, environment, configuration, positional, and default values as initial input.

InteractiveContext::set_bool

fn InteractiveContext::set_bool(self : InteractiveContext, option : ArgDef[Bool, OptionMetadata], value : Bool) -> Unit

Replaces a boolean option with a value selected interactively.

InteractiveContext::set_double

fn[Metadata] InteractiveContext::set_double(self : InteractiveContext, argument : ArgDef[Double, Metadata], value : Double) -> Unit

Replaces a floating-point input with a value selected interactively.

InteractiveContext::set_doubles

fn[Metadata] InteractiveContext::set_doubles(self : InteractiveContext, argument : ArgDef[Array[Double], Metadata], values : Array[Double]) -> Unit

Replaces repeated floating-point input with values selected interactively.

InteractiveContext::set_int

fn[Metadata] InteractiveContext::set_int(self : InteractiveContext, argument : ArgDef[Int, Metadata], value : Int) -> Unit

Replaces an integer option or positional with a value selected interactively.

InteractiveContext::set_int64

fn[Metadata] InteractiveContext::set_int64(self : InteractiveContext, argument : ArgDef[Int64, Metadata], value : Int64) -> Unit

Replaces a 64-bit integer input with a value selected interactively.

InteractiveContext::set_int64s

fn[Metadata] InteractiveContext::set_int64s(self : InteractiveContext, argument : ArgDef[Array[Int64], Metadata], values : Array[Int64]) -> Unit

Replaces repeated 64-bit integer input with values selected interactively.

InteractiveContext::set_ints

fn[Metadata] InteractiveContext::set_ints(self : InteractiveContext, argument : ArgDef[Array[Int], Metadata], values : Array[Int]) -> Unit

Replaces repeated integer input with values selected interactively.

InteractiveContext::set_string

fn[Metadata] InteractiveContext::set_string(self : InteractiveContext, argument : ArgDef[String, Metadata], value : String) -> Unit

Replaces a string option or positional with a value selected interactively.

InteractiveContext::set_strings

fn[Metadata] InteractiveContext::set_strings(self : InteractiveContext, argument : ArgDef[Array[String], Metadata], values : Array[String]) -> Unit

Replaces a repeated string option or positional with values selected interactively.

InteractiveContext::set_uint

fn[Metadata] InteractiveContext::set_uint(self : InteractiveContext, argument : ArgDef[UInt, Metadata], value : UInt) -> Unit

Replaces an unsigned integer input with a value selected interactively.

InteractiveContext::set_uint64

fn[Metadata] InteractiveContext::set_uint64(self : InteractiveContext, argument : ArgDef[UInt64, Metadata], value : UInt64) -> Unit

Replaces a 64-bit unsigned integer input with a value selected interactively.

InteractiveContext::set_uint64s

fn[Metadata] InteractiveContext::set_uint64s(self : InteractiveContext, argument : ArgDef[Array[UInt64], Metadata], values : Array[UInt64]) -> Unit

Replaces repeated 64-bit unsigned integer input with values selected interactively.

InteractiveContext::set_uints

fn[Metadata] InteractiveContext::set_uints(self : InteractiveContext, argument : ArgDef[Array[UInt], Metadata], values : Array[UInt]) -> Unit

Replaces repeated unsigned integer input with values selected interactively.

InteractiveContext::to_context

Returns the current context, including values already selected by this callback.

NonEmptyArray

pub struct NonEmptyArray[T] {
first : T
rest : ArrayView[T]
all : ReadOnlyArray[T]
} derive(
Debug
)

Non-empty view returned by required plural getters. first is the first value, rest is the remaining view, and all preserves the full sequence.

OptionMetadata

pub struct OptionMetadata {
type_ : OptionType
short : Char
description : String
env : String?
required : Bool
default_value : String?
multiple : Bool
interactive : Bool
} derive(
Debug
)

Metadata used to build and resolve a named option, including its short flag, environment key, configuration key, required state, and multiplicity.

OptionType

pub enum OptionType {
StringOpt
BoolOpt
IntOpt
Int64Opt
UIntOpt
UInt64Opt
DoubleOpt
} derive(Eq,
Debug
)

The scalar value kinds supported by options and positional arguments.
impl Show for OptionType

PositionMetadata

pub struct PositionMetadata {
type_ : OptionType
description : String
required : Bool
multiple : Bool
interactive : Bool
} derive(
Debug
)

Metadata used to build and resolve a positional argument.

bool

fn bool(name : String, short? : Char, description? : String, env? : String, config? : String, interactive? : Bool) -> ArgDef[Bool, OptionMetadata]

Defines a boolean flag. An omitted flag resolves to false; environment values use the boolean literals accepted by core/argparse.

build_command

Builds a core/argparse command from a declarative command definition. This is useful when an embedding application needs to parse the command itself instead of running a CliApp.

double

fn double(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, default? : Double?, interactive? : Bool) -> ArgDef[Double, OptionMetadata]

Defines a scalar double-precision floating-point option.

doubles

fn doubles(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[Double], OptionMetadata]

Defines a repeated double-precision floating-point option.

int

fn int(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, default? : Int?, interactive? : Bool) -> ArgDef[Int, OptionMetadata]

Defines a scalar signed integer option with optional defaults and required validation.

int64

fn int64(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, default? : Int64?, interactive? : Bool) -> ArgDef[Int64, OptionMetadata]

Defines a scalar 64-bit signed integer option.

int64s

fn int64s(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[Int64], OptionMetadata]

Defines a repeated 64-bit signed integer option.

ints

fn ints(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[Int], OptionMetadata]

Defines a repeated signed integer option. Use Context::get_ints to read all values after parsing.

position_double

fn position_double(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Double, PositionMetadata]

Defines a scalar double-precision floating-point positional argument.

position_doubles

fn position_doubles(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[Double], PositionMetadata]

Defines a variadic double-precision floating-point positional argument.

position_int

fn position_int(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Int, PositionMetadata]

Defines a scalar signed integer positional argument.

position_int64

fn position_int64(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Int64, PositionMetadata]

Defines a scalar 64-bit signed integer positional argument.

position_int64s

fn position_int64s(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[Int64], PositionMetadata]

Defines a variadic 64-bit signed integer positional argument.

position_ints

fn position_ints(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[Int], PositionMetadata]

Defines a variadic signed integer positional argument.

position_string

fn position_string(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[String, PositionMetadata]

Defines a scalar string positional argument. A required position is checked by the parser unless an interactive callback or configured value supplies it.

position_strings

fn position_strings(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[String], PositionMetadata]

Defines a variadic string positional argument. Read all values with Context::get_strings.

position_uint

fn position_uint(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[UInt, PositionMetadata]

Defines a scalar unsigned integer positional argument.

position_uint64

fn position_uint64(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[UInt64, PositionMetadata]

Defines a scalar 64-bit unsigned integer positional argument.

position_uint64s

fn position_uint64s(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[UInt64], PositionMetadata]

Defines a variadic 64-bit unsigned integer positional argument.

position_uints

fn position_uints(name : String, description? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[UInt], PositionMetadata]

Defines a variadic unsigned integer positional argument.

string

fn string(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, default? : String?, interactive? : Bool) -> ArgDef[String, OptionMetadata]

Defines a scalar string option. Set required when the command must receive a value and default when a fallback should be used. env and config select independent environment and configuration keys.

strings

fn strings(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[String], OptionMetadata]

Defines a repeated string option. Values are returned by Context::get_strings; configuration values must be JSON arrays.

uint

fn uint(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, default? : UInt?, interactive? : Bool) -> ArgDef[UInt, OptionMetadata]

Defines a scalar unsigned integer option.

uint64

fn uint64(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, default? : UInt64?, interactive? : Bool) -> ArgDef[UInt64, OptionMetadata]

Defines a scalar 64-bit unsigned integer option.

uint64s

fn uint64s(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[UInt64], OptionMetadata]

Defines a repeated 64-bit unsigned integer option.

uints

fn uints(name : String, short? : Char, description? : String, env? : String, config? : String, required? : Bool, interactive? : Bool) -> ArgDef[Array[UInt], OptionMetadata]

Defines a repeated unsigned integer option.

Powered by MoonBit

Site sourceReport issuePackagesBuild queueSkillsStatistics

© 2026 mooncakes.io