CLI framework for Swift: creating console utilities on iOS and macOS
Developing console applications (CLI — Command Line Interface) for the Apple ecosystem has long been the domain of Python, Ruby, or Bash. However, with the advent of Swift and its powerful toolset, including Swift Package Manager (SPM), it became possible to create fast, typed, and easily maintainable console utilities in the native language for iOS/macOS. In this article, we will take a detailed look at the main framework for building CLI in Swift — Apple's ArgumentParser, as well as alternative solutions.
What is a CLI framework for Swift?
A CLI framework is a library that handles routine tasks such as parsing command-line arguments, generating help, error handling, and command organization. In the Swift world, the de facto standard is ArgumentParser, developed by Apple and part of Swift Open Source. It allows you to declaratively describe your utility's interface, and it does everything else automatically.
Key features of ArgumentParser:
- Declarative command definition — you describe the structure, and the framework parses the arguments itself.
- Automatic help — the
--helpand-hflags are generated automatically. - Support for nested commands (like in
gitorswift). - Type validation — if a number is expected but a string is passed, a clear error will be displayed.
- Integration with SPM — just add a dependency in
Package.swift.
Installation and setup
To get started, you will need Swift 5.5+ (recommended 5.7 or newer). Create a new console project via SPM:
mkdir MyCLIcd MyCLIswift package init --type executableThen edit Package.swift by adding a dependency on ArgumentParser:
// swift-tools-version:5.7import PackageDescription
let package = Package( name: "MyCLI", dependencies: [ .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.2.0") ], targets: [ .executableTarget( name: "MyCLI", dependencies: [ .product(name: "ArgumentParser", package: "swift-argument-parser") ] ) ])Now update the dependencies and open the project:
swift package updateopen Package.swift # will open in XcodeCreating your first command
Create a file main.swift (or Sources/MyCLI/main.swift) with the following content:
import ArgumentParser
struct Greet: ParsableCommand { static let configuration = CommandConfiguration( abstract: "Greet the user", discussion: "This command outputs a personalized greeting." )
@Argument(help: "User's name") var name: String
@Option(name: .shortAndLong, help: "Number of repetitions") var count: Int = 1
@Flag(name: .shortAndLong, help: "Show version") var verbose: Bool = false
mutating func run() throws { if verbose { print("Version 1.0.0") } for _ in 0..<count { print("Hello, \\(name)!")
}
}
}
Greet.main()Now build and run:
swift run MyCLI Swift --count 3# Output:# Hello, Swift!# Hello, Swift!# Hello, Swift!
swift run MyCLI --help# Usage: MyCLI <name> [--count <count>] [--verbose]# Greet the user# ...Nested commands (subcommands)
For creating complex utilities (like
Also in library
Task Scheduler in C# (.NET): Quartz.NET, Hangfire and Coravel
Redis-rs for Rust: Complete Guide with Examples
node-cache: Simple and Efficient Caching in Node.js
Elasticsearch client for Go (Golang): complete guide to working with ES
Event Bus and Observer Pattern in Kotlin: Implementation and Examples