CLI framework for Swift: creating console utilities on iOS/macOS

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

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 --help and -h flags are generated automatically.
  • Support for nested commands (like in git or swift).
  • 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 executable


Then 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 Xcode


Creating 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

Recommendations