Mojo Command Line Args

Command-line arguments let users pass information to your program at launch time without modifying the source code. A data processing tool can accept a file path, a batch size tool can accept a number, and a utility can accept flags that change its behavior — all through arguments typed after the program name in the terminal.

How Arguments Work

  Terminal command:
  magic run mojo process.mojo data.csv 100 --verbose

  Inside your program:
  argv[0] = "process.mojo"   ← the program itself
  argv[1] = "data.csv"       ← first argument
  argv[2] = "100"            ← second argument
  argv[3] = "--verbose"      ← third argument (a flag)

  All arguments arrive as strings. Your program converts them as needed.

Reading Arguments with sys.argv

from sys import argv

fn main():
    var args = argv()
    print("Total arguments:", len(args))

    for i in range(len(args)):
        print("argv[" + String(i) + "] =", args[i])

Run it as: magic run mojo myapp.mojo hello world 42

Output:

Total arguments: 4
argv[0] = myapp.mojo
argv[1] = hello
argv[2] = world
argv[3] = 42

Accessing Specific Arguments

from sys import argv

fn main() raises:
    var args = argv()

    if len(args) < 2:
        print("Usage: program <name>")
        return

    var name = args[1]
    print("Hello,", name)
Command: magic run mojo greet.mojo Alice
Output:  Hello, Alice

Command: magic run mojo greet.mojo
Output:  Usage: program <name>

Converting Argument Types

Arguments arrive as strings. Convert them to numbers when your program needs arithmetic.

from sys import argv

fn main() raises:
    var args = argv()

    if len(args) < 3:
        print("Usage: add <num1> <num2>")
        return

    try:
        var a = Int(args[1])
        var b = Int(args[2])
        print(a, "+", b, "=", a + b)
    except:
        print("Error: both arguments must be integers")
Command: magic run mojo add.mojo 15 27
Output:  15 + 27 = 42

Command: magic run mojo add.mojo hello 5
Output:  Error: both arguments must be integers

Parsing Flags

Flags are arguments that begin with -- and enable optional behaviors. Parse them by scanning all arguments for recognized flag names.

from sys import argv

fn has_flag(args: List[String], flag: String) -> Bool:
    for i in range(len(args)):
        if args[i] == flag:
            return True
    return False

fn flag_value(args: List[String], flag: String) -> String:
    for i in range(len(args) - 1):
        if args[i] == flag:
            return args[i + 1]
    return ""

fn main():
    var args = argv()

    var verbose = has_flag(args, "--verbose")
    var output  = flag_value(args, "--output")

    if verbose:
        print("[verbose] Starting program")
        print("[verbose] Argument count:", len(args))

    if output != "":
        print("Writing output to:", output)
    else:
        print("No output file specified — using stdout")
Command: magic run mojo tool.mojo --verbose --output results.txt

Output:
  [verbose] Starting program
  [verbose] Argument count: 4
  Writing output to: results.txt

A Complete CLI Argument Parser

from sys import argv

struct Args:
    var input_file:  String
    var output_file: String
    var verbose:     Bool
    var max_lines:   Int

    fn __init__(inout self):
        self.input_file  = ""
        self.output_file = "output.txt"
        self.verbose     = False
        self.max_lines   = 0

fn parse_args() raises -> Args:
    var raw = argv()
    var result = Args()

    if len(raw) < 2:
        raise Error("Usage: program <input> [--output file] [--verbose] [--max N]")

    result.input_file = raw[1]   # positional: first argument is the input file

    var i = 2
    while i < len(raw):
        var arg = raw[i]
        if arg == "--output" and i + 1 < len(raw):
            result.output_file = raw[i + 1]
            i += 2
        elif arg == "--verbose":
            result.verbose = True
            i += 1
        elif arg == "--max" and i + 1 < len(raw):
            result.max_lines = Int(raw[i + 1])
            i += 2
        else:
            i += 1

    return result

fn main() raises:
    try:
        var args = parse_args()
        if args.verbose:
            print("Input:", args.input_file)
            print("Output:", args.output_file)
            print("Max lines:", args.max_lines)
        print("Processing", args.input_file, "...")
    except e:
        print(str(e))
Command:
  magic run mojo proc.mojo data.csv --output results.csv --verbose --max 500

Output:
  Input: data.csv
  Output: results.csv
  Max lines: 500
  Processing data.csv ...

Argument Validation Pattern

from sys import argv

fn validate_args(args: List[String]) raises:
    if len(args) < 2:
        raise Error("Missing required argument: filename")

    var filename = args[1]
    if not filename.endswith(".csv") and not filename.endswith(".txt"):
        raise Error("Unsupported file type: " + filename + " (use .csv or .txt)")

fn main() raises:
    try:
        validate_args(argv())
        print("Arguments valid — proceeding")
    except e:
        print("Argument error:", str(e))

Key Takeaways

Access command-line arguments with argv() from the sys module. argv()[0] is always the program name; user-provided arguments start at index 1. All arguments arrive as strings — convert to Int or Float64 inside a try/except for safety. Parse flags by scanning for strings that start with --. Parse flag values by reading the argument at the next index after the flag name. Always validate argument count and types early and print a usage message when requirements are not met, so users understand what went wrong.

Leave a Comment

Your email address will not be published. Required fields are marked *