Swiftpack.co - Package - SDGGiesbrecht/SDGCommandLine


macOS • Linux

APIs: SDGCommandLineSDGCommandLineTestUtilities


SDGCommandLine provides tools for implementing a command line interface.

יְהַלְלוּ אֶת־שֵׁם יהוה כִּי הוּא צִוָּה וְנִבְרָאוּ׃
May they praise the name of the Lord, for He commanded and they came into being!

                                                                                                    ―a psalmist


  • Automatic parsing of options and subcommands
  • Automatic help subcommand
  • Testable output
  • Colour formatting tools
    • Automatic •no‐colour option
  • Interface localization
    • Automatic set‐language subcommand to set language preferences.
    • Automatic •language option to run in a specific language only once.
  • Versioning tools
    • Automatic version subcommand
    • Automatic •use‐version option to attempt to download and temporarily use a specific version instead of the one which is installed (only for public Swift packages).

(For a list of related projects, see here.)


SDGCommandLine provides libraries for use with the Swift Package Manager.

Simply add SDGCommandLine as a dependency in Package.swift and specify which of the libraries to use:

let package = Package(
    name: "MyPackage",
    dependencies: [
        .package(url: "https://github.com/SDGGiesbrecht/SDGCommandLine", .upToNextMinor(from: Version(0, 3, 3))),
    targets: [
        .target(name: "MyTarget", dependencies: [
            .productItem(name: "SDGCommandLine", package: "SDGCommandLine"),
            .productItem(name: "SDGCommandLineTestUtilities", package: "SDGCommandLine"),

The libraries’ modules can then be imported in source files:

import SDGCommandLine
import SDGCommandLineTestUtilities

Example Usage

This example creates a tool with the following interface:

$ parrot speak

$ parrot speak •phrase "Hello, world!"
Hello, world!

main.swift must consist of the following lines:

ProcessInfo.applicationIdentifier = "tld.Developper.Parrot"
ProcessInfo.version = Version(1, 0, 0)
ProcessInfo.packageURL = URL(string: "https://website.tld/Parrot")


The rest can be anywhere in the project (but putting it in a separate, testable library module is recommended):

import SDGCommandLine

public let parrot = Command(name: UserFacing<StrictString, MyLocalizations>({ _ in "parrot" }),
                            description: UserFacing<StrictString, MyLocalizations>({ _ in "behaves like a parrot." }),
                            subcommands: [speak])

let speak = Command(name: UserFacing<StrictString, MyLocalizations>({ _ in "speak" }),
                    description: UserFacing<StrictString, MyLocalizations>({ _ in "speaks." }),
                    directArguments: [],
                    options: [phrase],
                    execution: { (_, options: Options, output: Command.Output) throws -> Void in

                        if let specific = options.value(for: phrase) {
                        } else {

let phrase = Option<StrictString>(name: UserFacing<StrictString, MyLocalizations>({ _ in "phrase" }),
                                  description: UserFacing<StrictString, MyLocalizations>({ _ in "A custom phrase to speak." }),
                                  type: ArgumentType.string)

enum MyLocalizations : String, InputLocalization {
    case english = "en"
    internal static let cases: [MyLocalizations] = [.english]
    internal static let fallbackLocalization: MyLocalizations = .english

Tests are easy to set up:

func testParrot() {
    do {
        let output = try parrot.execute(with: ["speak", "•phrase", "Hello, world!"])
        XCTAssertEqual(output, "Hello, world!")
    } catch {
        XCTFail("The parrot is not co‐operating.")


The SDGCommandLine project is maintained by Jeremy David Giesbrecht.

If SDGCommandLine saves you money, consider giving some of it as a donation.

If SDGCommandLine saves you time, consider devoting some of it to contributing back to the project.

Ἄξιος γὰρ ὁ ἐργάτης τοῦ μισθοῦ αὐτοῦ ἐστι.
For the worker is worthy of his wages.



Stars: 1
Help us keep the lights on



0.3.3 - Jun 29, 2018

Bug Fixes

  • Fixed several corner cases where other error types escaped being wrapped in an Command.Error.

0.3.2 - Jun 28, 2018

Bug Fixes

  • Dependencies have been updated.

0.3.1 - May 31, 2018

Dependency updates only.

0.3.0 - May 4, 2018

Breaking Changes

  • initialize() has been removed. Set ProcessInfo.applicationIdentifier, ProcessInfo.version and ProcessInfo.packageURL instead.
  • Command.Output is now a class. Instead of print(..., to: &output), use output.print(...).
  • Command.execute(...) now provides the output with thrown errors. In order to do so, other error types now get wrapped in a Command.Error.)
  • Low quality localizations have been dropped.

New Features

  • New argument types are provided:
    • integer(range:) (→ Int)
    • path (→ URL)
  • Commands and options can now be hidden from the “help” lists. (See their respective initializers.)
  • A new empty‐cache subcommand is available. It deletes anything saved to FileManager.url(in: .cache, [...]), including cached alternate versions.
  • New module to aid in writing tests: SDGCommandLineTestUtilities.
  • A new test mode (Command.Output.testMode) can be engaged to prevent command output from appearing amid test results.

0.2.0 - Apr 10, 2018

Breaking Changes

  • Swift 4.1