# Command line UX enhancements for \`swift\`

**URL:** <https://forums.swift.org/t/command-line-ux-enhancements-for-swift/50670>\
**Category:** Pitches\
**Created:** [July 26, 2021, 5:25pm UTC](https://forums.swift.org/t/command-line-ux-enhancements-for-swift/50670 "2021-07-26T17:25:23Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![bitjammer](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bitjammer/32/18612_2.png) [@bitjammer](https://forums.swift.org/u/bitjammer)\
**Post date:** [July 26, 2021, 5:25pm UTC](https://forums.swift.org/t/command-line-ux-enhancements-for-swift/50670/1 "2021-07-26T17:25:23Z")

</div>

Hello everyone,

I’d like to start a thread about how to improve Swift’s user experience from the command line across all platforms.

Specifically, I’d like to make the command line interface more appropriate for direct, interactive use by humans, while keeping automation use cases available. I propose to rework the CL tools in the following ways:

- Give users direction in accomplishing their Swift tasks at the command line, providing choices for high level tasks and clarification about what to do next where possible.
- Progressively disclose flags and options, keeping text focused on the current task.
- Make the command line aware of context so it can infer the right action for impactful cases.
- Continue to provide explicit invocations for all of the tasks we perform today.

## Motivation

The Swift CLI has grown organically over time to include a large number of flags and options for many individual needs. In fact, you could argue the CLI was never truly “designed” to scale to the features it offers today. In order to use it successfully, you need to know which combination of options go together for a given task, many of which are designed to be driven by an IDE or build system, not a human. In fact, typing `swift --help` presents around 150 lines of options, with `--help-hidden` increasing the count to around 250. The tool would greatly benefit from a true UX design.

The command line is also currently inconsistent with how it presents options, for example:

- Typing `swift --help` implies compilation with the driver and presents many build-related options, but also presents other unrelated subcommands.
- With no arguments, `swift` invokes the REPL, but this isn’t particularly obvious.
- The `swift build` command is for packages, but we also elevate raw code compilation with the `swiftc` command.

As a top goal of a redesign, the command line should always presents clear, consistent, and intuitive avenues through high level tasks. The use of sub-commands will make grouping of tasks more logical and easier to discover. This approach will also make it easier to add new functionality while keeping the commands organized, and more approachable for developers of all experience levels.

Once the top-level commands are better organized, I’d like to add features that further elevate the value of sample code and documentation, too. We can make the CL experience easier for newcomers learning the language, and for anyone investigating a new package or code base to learn it by example.

## Design Sketch

The proposed idea, broken down into a few sub-goals:

### 1. Establish a concise, colorful look and feel.

To improve readability and differentiation of descriptions, lists, menus, or code listings printed to the terminal, I’d like to adopt terminal colors and establish a concise and spacious look and feel to the text. To give an example of a project that has some inspiring similarities, check out the GitHub CLI: [https://cli.github.com](https://cli.github.com/).

### **2. Make the `swift` command act as a high-level router to subcommands.**

With the arrival of the Swift Package Manager, we’ve already been moving in this direction. I'd like to continue with an additional focus on subcommands. For example, today the `swift` command will assume you mean to invoke the compiler when there isn't a subcommand, although it's not clear that is always the intended outcome, and we have `swiftc` for that case, as well.

The change I propose here is to just list the highest level subcommands instead, when there isn’t anything more specific requested. There are two small branches I have ready to get this started which include some improvements to the presentation, as well:

[https://github.com/bitjammer/swift-driver/tree/acgarland/help-intro](https://github.com/bitjammer/swift-driver/tree/acgarland/help-intro)

> **[GitHub - bitjammer/llvm-project at acgarland/swift-repl-help-text](https://github.com/bitjammer/llvm-project/tree/acgarland/swift-repl-help-text)**
>
> acgarland/swift-repl-help-text

 ![Screen Shot 2021-07-26 at 10.24.09 AM](https://global.discourse-cdn.com/swift/original/3X/1/1/1152639efbd6d4c29a49095e901c9dbf8805bd05.jpeg)

### **3. Require the `swift repl` command to launch the REPL**

Launching the REPL should be consistent with the other `swift` subcommands. The tools already recognize `swift repl` as a subcommand, and will become much more discoverable when listed among the top subcommands in the new UX. By not launching the REPL by default, room is opened up for other default behaviors based on context (see next section.)

### **4. Run certain subcommands automatically based on context**

When you run a tool like `swift` with no parameters, the default behavior is generally chosen to either 1) encourage specific user behavior, or 2) do the thing users most often want. Preferably, something happens that feels like both. Given the user’s context, we can pick default behaviors more likely to be helpful for the user. For instance, if your shell’s current folder is within the root of a package, it may make sense to list all targets within that package if you just type `swift`, or provide a menu to explore and run code snippets.

**Proposed new behavior: code snippets.** The first contextual behavior I’d like to propose is a new way to explore a package. Imagine an interactive help experience that surfaces a package's documentation, and can even browse and run a package's bundled code snippets. Every time you download a new Swift package, you can immediately experience how that code is used in focused examples.

I have been prototyping some ideas on snippets specifically, and would love to spend some time to get feedback and go deeper on this soon in a separate pitch. The approach is designed to make it much more rewarding to document packages, and provide example code showing off the API. And if the idea catches on, the Swift community will benefit from a standard way to learn about new packages more easily.

I’ll try to post some code and a further pitch on this idea soon.

Consistency is still very important, so even if we offer contextual behaviors, every option the user may want will also need a specific command to perform that task with 100% reliability.

**5. The `swiftc` command continues to serve as the way to automate compilation.**

The `swiftc` tool already exists for direct control of the Swift compiler. Again, for consistency, a command such as `swift compile` could be added to the main `swift` command, and to complement the `swift build` command.

What this end state means is that the `swift` command serves as an entry point for people to perform high-level tasks with Swift, and `swiftc` is dedicated to compilation with the driver.

---

<div class="post-metadata">

**Author:** ![nikitamounier](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nikitamounier/32/24825_2.png) [@nikitamounier](https://forums.swift.org/u/nikitamounier)\
**Post date:** [July 27, 2021, 2:08pm UTC](https://forums.swift.org/t/command-line-ux-enhancements-for-swift/50670/2 "2021-07-27T14:08:56Z")

</div>

This looks like a long-needed and thoughtful improvement!

---

<div class="post-metadata">

**Author:** ![bitjammer](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bitjammer/32/18612_2.png) [@bitjammer](https://forums.swift.org/u/bitjammer)\
**Post date:** [August 5, 2021, 8:55pm UTC](https://forums.swift.org/t/command-line-ux-enhancements-for-swift/50670/4 "2021-08-05T20:55:12Z")

</div>

Here is a test toolchain for Linux with the the above mentioned PRs in case anyone wants to try it out. Still working on getting a macOS toolchain built.

[https://ci.swift.org/job/swift-PR-toolchain-Linux/634//artifact/branch-main/swift-PR-34262-634-ubuntu16.04.tar.gz](https://ci.swift.org/job/swift-PR-toolchain-Linux/634//artifact/branch-main/swift-PR-34262-634-ubuntu16.04.tar.gz)

---

<div class="post-metadata">

**Author:** ![bitjammer](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bitjammer/32/18612_2.png) [@bitjammer](https://forums.swift.org/u/bitjammer)\
**Post date:** [August 13, 2021, 5:13am UTC](https://forums.swift.org/t/command-line-ux-enhancements-for-swift/50670/5 "2021-08-13T05:13:04Z")

</div>

Here's a macOS toolchain as well. [https://ci.swift.org/job/swift-PR-toolchain-osx/1077/artifact/branch-main/swift-PR-34262-1077-osx.tar.gz](https://ci.swift.org/job/swift-PR-toolchain-osx/1077/artifact/branch-main/swift-PR-34262-1077-osx.tar.gz)

---

<div class="post-metadata">

**Author:** ![bitjammer](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bitjammer/32/18612_2.png) [@bitjammer](https://forums.swift.org/u/bitjammer)\
**Post date:** [September 10, 2021, 3:49pm UTC](https://forums.swift.org/t/command-line-ux-enhancements-for-swift/50670/6 "2021-09-10T15:49:29Z")

</div>

As promised, continuing the discussion with snippets here: [Swift Snippets](https://forums.swift.org/t/swift-snippets/51947)

---

<div class="post-metadata">

**Author:** ![mklbtz](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mklbtz/32/21972_2.png) [@mklbtz](https://forums.swift.org/u/mklbtz)\
**Post date:** [September 10, 2021, 9:36pm UTC](https://forums.swift.org/t/command-line-ux-enhancements-for-swift/50670/7 "2021-09-10T21:36:26Z")

</div>

I really love all the ideas you pitched here! Giving the CLI a redesign sounds like a great idea and will only become more relevant as it grows. Love the idea of using colors and having the default swift command be more… explanatory.

The contextual stuff is interesting. I can’t think of any other CLI I’ve used that works this way. Do you have some examples that you’re using as inspiration for this idea? I’d love to see more examples.

---

<div class="post-metadata">

**Author:** ![dannys42](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dannys42/32/3994_2.png) [@dannys42](https://forums.swift.org/u/dannys42)\
**Post date:** [September 19, 2021, 3:40pm UTC](https://forums.swift.org/t/command-line-ux-enhancements-for-swift/50670/8 "2021-09-19T15:40:30Z")

</div>

Disclaimer: I thinks this comment may be tangent to your primary goal, but you touch on a number of aspects of the topic, so I'd like to chime in with my long-standing Unix CLI pipe dream in case it inspires anyone. 🙂

Typical unix argument processing (getopt/getopt-long style) is generally a wonderful boon to flexibility and automation for command-line programs. However it's always difficult to build UI's around CLI tools as each one is totally unique.

It would be awesome if there was a standard command for doing an argument schema dump so that UI tools can query the tool and programmatically build reasonably useful UI experiences around the CLI tool without having specific knowledge of the CLI tool itself. (I realize there will always be edge cases where specific knowledge will be beneficial, but the intent is to minimize those cases).

In this way any interactive user interface, whether graphical or command-line like the use-case you mention above, can (ideally) be built as a generic library. Perhaps in cases where the interface is built with the application, this library can then allow explicit programming of specific edge case.

As way of example, the idea is to have the argument processing library always accept a flag like "--dump-argument-schema"...

```swift
USAGE: some_cli [--port <port>] [...]

OPTIONS:
  -p, --port <port> TCP Port to listen on (Default: 8000) (default: 8000)
  ...
  --dump-argument-schema Dump argument schema -- perhaps a hidden argument?
  -h, --help Show help information.

```

Perhaps the flag should take a parameter like `json`, `xml`, etc. to specify the format to dump in. But the idea is then everything necessary to build a meaningful UI would be in the schema (grouped commands, command exclusion rules, valid values, or other value validation rules, etc.)

Having this extra layer also gives the potential for easily switching UI implementations... allowing for experimentation in the UI without breaking things for existing users.

---

<div class="post-metadata">

**Author:** ![jawbroken](https://avatars.discourse-cdn.com/v4/letter/j/cc9497/32.png) [@jawbroken](https://forums.swift.org/u/jawbroken)\
**Post date:** [September 19, 2021, 6:55pm UTC](https://forums.swift.org/t/command-line-ux-enhancements-for-swift/50670/9 "2021-09-19T18:55:42Z")

</div>

You could start by looking at how [Swift Argument Parser](https://github.com/apple/swift-argument-parser) could be adapted for generating UI interfaces (or schema).
