Skip to content

Swift Argument Parser

Developer UtilitiesCLI/UtilsSwift

What it is

Apple's official library for building command-line tools in Swift, generating parsing, validation and help text from a declared struct.

Conform a struct to ParsableCommand and declare @Argument, @Option and @Flag properties. Help text and validation come from the declarations.

Installation

.package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0")

Getting started

The smallest useful thing you can do with it, and what each part means.

A command from a struct
import ArgumentParser

@main
struct Library: ParsableCommand {
    static let configuration = CommandConfiguration(
        abstract: "Manage a book library.",
        subcommands: [Add.self, Remove.self],
        defaultSubcommand: Add.self
    )
}

struct Add: ParsableCommand {
    @Argument(help: "The book title.")
    var title: String

    @Option(name: .shortAndLong, help: "Publication year.")
    var year: Int?

    @Flag(name: .shortAndLong, help: "Verbose output.")
    var verbose = false

    func validate() throws {
        guard title.count <= 200 else {
            throw ValidationError("Title must be 200 characters or fewer.")
        }
    }

    mutating func run() throws {
        if verbose { print("adding \(title)") }
        try store.add(title: title, year: year)
    }
}
validate() runs before run(), so bad input is rejected with a clean message and exit code rather than partway through the command's work.

Advanced usage

Where the library earns its place over a simpler alternative.

Async commands, enums and completions
enum Format: String, ExpressibleByArgument, CaseIterable {
    case json, yaml, text
}

struct Export: AsyncParsableCommand {
    @Option var format: Format = .json
    @OptionGroup var common: CommonOptions   // reusable option groups

    func run() async throws {
        let data = try await api.fetchAll()
        try write(data, as: format)
    }
}

struct CommonOptions: ParsableArguments {
    @Option(help: "Config file path.")
    var config: String = "~/.library.toml"
}

// Shell completions come free:
//   library --generate-completion-script zsh > _library
Conforming an enum to ExpressibleByArgument means invalid values are rejected by the parser and the valid ones appear in help and completions automatically.

Errors and fixes

The failures you are most likely to hit, and what actually resolves them.

Missing expected argument
A non-optional @Argument was omitted. Give it a default or make the type optional.
run() is never called
The type is not the @main entry point, or a subcommand is missing from configuration.subcommands.

Best practices

  • Use validate() for input checks so failures are clean and exit codes correct.
  • Model choices as CaseIterable enums rather than validating strings by hand.
  • Use @OptionGroup to share common options across subcommands.
  • Ship the generated completion script; it costs nothing and improves usability.

Background

Why it exists, and what it was reacting to.

Written by the Swift team and used by Swift's own tooling, it turns argument parsing into a matter of declaring properties with property wrappers.