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.
swift
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)
}
}Advanced usage
Where the library earns its place over a simpler alternative.
swift
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 > _libraryErrors 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.
