A guide to help you write better command-line programs, taking traditional UNIX principles and updating them for the modern day.

  • By Command Line Interface Guidelines
  • Last update: Jan 8, 2023
  • Comments: 16

Command Line Interface Guidelines

An open-source guide to help you write better command-line programs, taking traditional UNIX principles and updating them for the modern day.

This is the source code for the guide. To read it, go to clig.dev.

Join us on Discord if you want to discuss the guide, or just chat about CLI design.


The content of the guide lives in a single Markdown file, content/_index.md. The website is built using Hugo.

To run Hugo locally to see your changes, run:

$ brew install hugo
$ cd <path>/<to>/cli-guidelines/
$ hugo server

To view the site on an external mobile device, run:

hugo server --bind --baseURL http://$(hostname -f):1313


This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.




  • 1

    Broken (non-portable?) ls flags example

    At one point, the guidelines suggest that if it were written today, ls might have the default flags lhFGT. This doesn't work for me in Ubuntu 20.04:

    $ ls -lhFGT
    ls: option requires an argument -- 'T'
    Try 'ls --help' for more information.

    (but more importantly: awesome guide, thanks for putting it together)

  • 2

    Do not accept secrets via environment variables

    I don't think this is at all controversial, is it?

    mysql accepted a MYSQL_PWD env var forever, and it's finally been deprecated and will eventually be removed.

    From their docs:

    Use of MYSQL_PWD to specify a MySQL password must be considered extremely insecure and should not be used. Some versions of ps include an option to display the environment of running processes. On some systems, if you set MYSQL_PWD, your password is exposed to any other user who runs ps. Even on systems without such a version of ps, it is unwise to assume that there are no other methods by which users can examine process environments.

    MYSQL_PWD is deprecated as of MySQL 8.0; expect it to be removed in a future version of MySQL.

  • 3

    Best way to extend/superset these guidelines?

    Hi! As it turns out, y'all releasing this was super timely, as I was working with some folks at my job on coming up with some CLI guidelines that we could use organizationally and for our public tool. What I'm wondering is more your thoughts on how you imagine people extending or building on top of these:

    • Is the preferred model "centralize everything, send us PRs for what you want to modify so we can all share a single standard, and don't have your own guidelines on top of this"?
    • Is the right way to do this to fork your guidelines, keeping all the appropriate attribution of course, but changing styles/name/etc?
    • Is it better to just link back to your guidelines and somehow have a system for saying "they say this, but actually we say this other thing instead"?

    I'd love to hear about what y'all think. This is a fantastic, amazing document and I definitely think it's the right thing to build anything on top of.

  • 4

    Clamp maximum font size

    On a 3440x1440 monitor at full screen, the body text size is ~41.28px (1vw * 1.2rem, where 1vw = 34.40px), which is pretty hard to read. The font size at >1600px could be clamped at 20px, rather than its current 1vw * 1.2rem.

  • 5

    Add docker pull multiple progress bars example

    While an animated illustration will be great, when ready, for now this static snapshot of the progress bars can be helpful for readers who may not be using Docker and do not know what the article is talking about.

    The example captures a good mix of states of various progress bars:

    • The first layer is downloaded and extracted to complete the pull
    • The second layer is in extraction stage
    • A few layers are downloaded completely as concurrent and independent steps but are waiting for their sequential steps
    • Two layers are still in their download phase with different percentages
  • 6

    argparse for Python argument parsing?

    I was surprised to not see argparse in the list of python cli libraries. Is there a particular reason why it is deemed not-great? Personally, the biggest thing it has going for it is that it's built in to Python, so you can use it for all your custom python scripts without needing to install third-party libraries.

  • 7

    Document FORCE_COLOR

    Document use of FORCE_COLOR variable which forces enablement of coloring and ignore the detection logic.

    There are other similar option used like CLI_COLOR, PY_COLORS but that one is by far the most popular option. This complements the NO_COLOR option with missed to cover for the opposite use-case when it was designed.

  • 8

    Adding a CLI argument parser for Deno

    Deno is a Javascript and TypeScript runtime, this pull request adds a link to a CLI argument parser (officially supported as it is part of Deno's standard library)

  • 9

    Args/flags: Use a cross-platform example for the set of default flags ls(1) might use if designed today

  • 10

    Add a CLI argument parser for Perl

    Thanks for this set of guidelines --- it's clear that a lot of hard work has gone into the philosophy and guidelines! Would you be willing to add Perl's standard argument parser to the list? Thank you for considering this PR!

  • 11

    Provide a repository with example implementations

    This is a fantastic resource, but from what I've found, it's not necessarily easy or straightforward in some languages to implement these solutions. Rather than requiring every developer to re-implement these guidelines from scratch in their language of choice, I would recommend creating a repository of implementations that provide support for this using the language's standard library.

    I would recommend using the Builder creational design pattern, as discussed on https://refactoring.guru/design-patterns/builder, to allow developers to control which features they support. I really appreciate the hard work and dedication of the team, and would love to implement these guidelines, but without more concrete resources, I've found at times it's unrealistic. Any solutions, example implementations, etc. would be very useful in my opinion for developers hoping to support this and be a good steward.

  • 12

    Permalinks don't open to the right spot in Firefox

    Just came across an odd navigational issue.

    When I open a new tab in Firefox 105.0.3 on a Mac and go to https://clig.dev/#environment-variables, I end up in different places depending on what machine I'm using. It appears to be some sort of race condition, because on one machine I end up in Errors, and on the other I end up in the Output section.

    Other notes:

    • Once I'm on the page, if I hit command-L and then return, I will correctly land on Environment Variables.
    • In Safari and Chrome, no issues.

    @ThinkMake any idea what may be happening here?

  • 13

    Localization for Chinese version

    Hi team,

    This CLI guideline is a good reference for designing CLI tooling. I am willing to help translate it into Chinese and promote it in the local community. May I start to work and contribute to this?

  • 14

    "Increase information density—with ASCII art!" is problematic for accessibility

    There is an item in the Output section that reads:

    **Increase information density—with ASCII art!** For example, `ls` shows permissions in a scannable way. When you first see it, you can ignore most of the information. Then, as you learn how it works, you pick out more patterns over time.

    Unfortunately, while ASCII art can be great for improving information density for some users, it is generally problematic for accessibility and inclusivity:

    • Screen reader users will generally have an experience ranging from "much more unpleasant than a visual user" (eg, with an ASCII art table) to "completely unusable" (eg, for most ASCII art progress indicators or product logos). Sections 5.3.2 and 5.4 of this research paper are good overviews of these issues.
    • It tends to create/exacerbate formatting issues with text wrapping at low line lengths, which disproportionately impacts users that need to use high zoom levels and/or font sizes
    • Very high information density can also make it harder for folks with certain types of neurodivergence to parse the output

    I think it would be preferable to rewrite the ASCII art item along these lines:

    **Avoid using ASCII art!** This includes product logos in help and splash screens, progress indicators, and table-like formatting. ASCII art generally creates accessibility problems. For example, screen readers will announce ASCII art character by character instead of as a whole, and users that require high font sizes might see mangled output due to line wrapping.
    **Table-like output requires extra caution.** Sometimes, a tool's output is naturally tabular, and it can make sense to support output formatted like a table. However, users of accessibility technologies (for example, screen readers) will not generally be able to navigate tabular CLI output column-wise or row-wise - they will be forced to read the output line-by-line. To make tabular output more inclusive:
    * **Allow the user to control the order and visibility of columns.** For example, `git log` provides both a `--format` flag that enables exact control over what data is displayed and several shorthand flags for different levels of information density.
    * **Do not use unicode formatting characters to separate columns visually.** Unnecessary characters like `╣` create noise for ATs.
    * **Support exporting tabular output to a tabular data format.** Users of accessibility technologies will be better able to navigate your table row-wise or column-wise if they can export it to, for example, a `.csv` file or an `.html` file with an embedded table.
    * **Any output visible in a table should also be present in other structured output formats.** For example, if you support a `--json` option, ensure that all the output exposed as a table is also exposed there.
    * **Avoid using tables to format non-tabular data.** For example, do not copy the default no-argument behavior of `ls`.

    I considered adding this as a comment on #5, but I thought this felt more immediately actionable when taken on its own, so I made it a separate issue.

  • 15

    Add explanation about syntax

    Add explanation about syntax.

    Building a syntax for a CLI is important because it gives a strong foundation for the CLI.

    It provides the following advantages:

    • Provide an intuitive guide to the CLI.
    • The difference between the different versions for a CLI can be easily extracted by executing $diff to the syntax.
    • Can be utilized to check the execption on the user input.
    • Etc.

    This commit explains how a syntax for a CLI can be establisihed, and the advantages.

    Limitation: need more examples.

    Signed-off-by: Myoung-Jun Lee [email protected]

  • 16

    "Make it easy to type." harms its credibility with "apple" vs. "orange"

    Make it easy to type. Some words flow across the QWERTY keyboard much more easily than others, and it’s not just about brevity. plum may be short but it’s an awkward, angular dance. apple trips you up with the double letter. orange is longer than both, but flows much better.

    This is too subjective to recommend in such an unqualified fashion.

    I'd take apple over orange any day because, now that you've brought them to my attention, I find that apple is significantly easier to type than orange... party because I'm still training my left hand to touch-type and partly because I actually find that doubled letters are easier to type.

    In fact, before I finished reading through your citation and concluded that you made that example out of whole cloth, the combination of that flawed example and the title "The Poetics of CLI Command Names" was giving me the false impression that Carl Tashian was some wishy-washy person who is not to be trusted because he gives subjective advice and claims it's objective.

    That said, I am curious why I and whoever wrote that have such different subjective experiences. Is it possible they're using a membrane keyboard or a laptop? I'm using a buckling-spring board, which is about as full-travel and tactile as you can get.