Build a command-line application
trb/cli generates a typed command-line parser and compiles the application as
one native executable. Its records, payload enums, and metadata are TypeRB
APIs; users do not program against Go APIs. The current native executable
backend requires mode: "go" and the Go toolchain. Ruby and TypeScript launcher
generation is not provided.
Define the schema
Use records for argument groups and a payload enum for subcommands:
import { run } from trb/cli
record ServeArgs
directory: String
port: Integer = 8080 @cli(:option, short: "p", about: "Port to listen on")
verbose: Boolean = false @cli(:option, short: "v", about: "Enable verbose output")
end
enum Command
Serve(args: ServeArgs) @cli(about: "Start the server")
Version @cli(about: "Print version details")
end
record AppArgs
command: Command @cli(:subcommand)
end
An unannotated field such as directory is positional. An option uses its
kebab-cased field name by default, so verbose becomes --verbose and
output_path becomes --output-path. name or long overrides the long
name; short must contain one character. Defaults belong to the record and are
also used by ordinary non-CLI construction. Subcommand names cannot begin with
-, long option names cannot contain =, and - is reserved from use as a
short option. U+0000 is also reserved in subcommand and option names because
it cannot appear in an operating-system argument; other Unicode names are
supported. trb check reports reserved names instead of generating help for
an option or command that the parser cannot select.
Use about and value_name to describe a positional field in generated help.
Options accept those keys plus name (or long) and short. The root
subcommand selector itself has no naming metadata; put name and about on
its enum members.
The root @cli(:subcommand) field is required and non-nullable and cannot have
a record default in the initial contract. Defaults and nullable types make
ordinary scalar positional or option fields omittable.
The record passed to run<...> must itself be non-nullable and non-generic in
the initial contract. Transparent non-generic aliases are accepted, but forms
such as run<AppArgs?> and run<AppArgs<Integer>> are reported before native
executable generation.
A transparent alias of the root record uses the same schema:
alias Arguments = AppArgs
args := run<Arguments>(name: "fileserver")
Parse and dispatch
Call run once from the application and match the returned payload enum:
def main()
args := run<AppArgs>(name: "fileserver", version: "1.0.0", about: "Serve a local directory")
case args.command
when Command::Serve(serve)
puts("serving " + serve.directory)
puts("port " + serve.port.to_s())
when Command::Version
puts("extended version details")
end
end
Typical calls are:
fileserver serve public
fileserver serve public --port 9000 --verbose
fileserver serve public -p 9000 -v
fileserver serve --help
fileserver --version
Long values may use --port=9000. -- ends option parsing. Boolean options
are flags and also accept an explicit long value such as --verbose=false.
Generated usage errors go to standard error and exit with status 2.
Compile one executable
The current native executable backend uses the Go toolchain. Configure the
project with mode: "go", then compile the entrypoint:
trb check
trb build --compile
./bin/fileserver --help
The generated parser uses only the Go standard library internally. The resulting program does not require a Go, Ruby, or JavaScript runtime, runtime reflection, or a separate schema file.
Initial contract
The first implementation supports scalar String, Integer, Float, and
Boolean fields, one root subcommand field, payloadless commands, and commands
with one record payload. Root options must appear before the subcommand.
Repeated values and Arrays, environment fallback, option aliases, validation constraints, mutually exclusive groups, shell completion, nested subcommands, optional or default root commands, and combined short flags are not yet supported. These are reserved as extensions to the same record and payload-enum schema. Dynamic plugins and Ruby or TypeScript launcher generation are outside the package's single-binary model.
trb/platform/go/cli was published in TypeRB 0.3.44 and remains accepted as a
compatibility import. Use trb/cli in new source.