Good CLI tools are intuitive, consistent, and user-friendly. Focus on clear parameters, sensible defaults, proper exit codes, STDOUT/STDERR separation, human- and machine-readable output, helpful error messages, and adherence to ecosystem conventions. Validate input, document options, and make the tool predictable — so users can trust and enjoy using it.Good CLI tools are intuitive, consistent, and user-friendly. Focus on clear parameters, sensible defaults, proper exit codes, STDOUT/STDERR separation, human- and machine-readable output, helpful error messages, and adherence to ecosystem conventions. Validate input, document options, and make the tool predictable — so users can trust and enjoy using it.

How to Design a CLI Tool That Developers Actually Love Using

2025/11/03 00:15

In my previous article, Master the Art of Command Line: Your Ultimate Guide to Developing Powerful Tools, we explored how to build a CLI tool from the ground up. Now, let’s take the next step — how do you make it good? Ultimately, the key lies in ease of use. A well-designed CLI feels intuitive, predictable, and efficient for the user. However, this ease of use is achieved through several distinct design principles, which we’ll explore in this article.

For demonstration, we’ll use the Click Python library, but the principles apply to almost any CLI framework you might use.

Parameters

Most CLI tools accept input from the user. In most cases, this input isn’t interactive — it comes in the form of parameters that define how the tool behaves.

For example, the cp command takes at least two parameters:

  1. The path to the file or directory to copy, and
  2. The path to the destination.

It can also accept optional parameters like -v, which enables verbose output.

Broadly, there are two types of parameters: required and optional. In most CLI libraries, required parameters are called arguments (or positional arguments), and optional parameters are called options.

Positional arguments

As the name suggests, positional arguments are determined by their position. The user provides values in a specific order, and the tool interprets them accordingly.

For instance, if the cp command expects two positional arguments — source and destination — the user would call it as:

cp source destination

Even if your tool requires input, it’s often cumbersome (and unnecessary) to make users specify every value manually. A good rule of thumb: if you can provide a sensible default, make it an option instead of an argument.

For example, a --log-level parameter could default to info. Forcing users to remember the position and always pass info doesn’t add value — it just adds friction.

Multiple Arguments

Sometimes a tool may need to accept multiple values for a single argument. A common example is specifying multiple source files to copy into a single destination directory. This allows the user to run one command instead of several:

cp source1 source2 destination

There are some caveats — typically, only one argument can accept multiple values. Your code (not the argument parser) must handle additional validation and logic.

Options

Options let users specify parameters by name, often in the form --option value. If the user doesn’t provide an option, the tool uses its default value.

For example:

--log-level debug

A special kind of option is a flag — it doesn’t take a value. The mere presence of the flag toggles a behavior, such as enabling verbose output:

--verbose

Option names should be clear and descriptive, so users can easily understand their purpose.

Example implementation:

@click.command() @click.option('--verbose', is_flag=True) @click.option('--log-level', default="info") @click.argument('srcs', nargs=-1) @click.argument('dst') def copy(verbose: bool, log_level: str, srcs: tuple[str, ...], dst: str): ...

Now, the tool can be called in several ways:

cp --verbose --log-level trace source1 source2 destination cp source destination

Short options

So far, we’ve used long option names. These are ideal for scripts, since they’re self-explanatory and easy to understand at a glance.

However, for quick, one-time commands, users often prefer short options — like -v instead of --verbose. Be selective when introducing short forms. Not every option needs one. If your tool has many options, you’ll quickly run out of intuitive letters — especially since multiple options might start with the same one. It’s usually enough to define short versions only for frequently used options.

Example:

@click.command() @click.option('-v', '--verbose', is_flag=True) @click.option('--log-level', default="info") @click.argument('srcs', nargs=-1) @click.argument('dst') def copy(verbose: bool, log_level: str, srcs: tuple[str, ...], dst: str): ...

Now both forms work:

cp -v source destination cp --verbose source destination

Validate user input and fail fast

A robust CLI tool should validate user input early and fail with a clear, actionable message. Most CLI frameworks support this pattern.

For example, Click can enforce valid log levels and path arguments automatically:

@click.command() @click.option('-v', '--verbose', is_flag=True) @click.option('--log-level', default="info", type=click.Choice(["debug", "info", "error"])) @click.argument('srcs', nargs=-1, type=click.Path()) @click.argument('dst', type=click.Path()) def copy(verbose: bool, log_level: str, srcs: tuple[str, ...], dst: str): ...

However, you may still need custom logic. In our copy example:

  • If there’s one source, the destination can be a file or directory.
  • If there are multiple sources, the destination must be a directory — otherwise files might overwrite each other unexpectedly.

Generic CLI libraries won’t handle such cases automatically, so this validation must live in your code.

Help message

A good tool always provides a good help message.

Users should be able to run something like --help to see:

  • What parameters are available
  • Their meaning
  • Accepted types or values (e.g., valid log levels)

A clear help message saves time, reduces errors, and improves user trust in your tool.

Follow your ecosystem patterns

Finally, great CLI tools feel native to their ecosystem. Study other tools in your environment and follow their conventions — especially for naming options and arguments.

For example, in the Unix world, tools like cp, mv, and rsync all use source and destination as positional arguments, with source always preceding destination.

Consistent naming and familiar option letters (-v for verbose, -r for recursive, -n for dry run, -h/--help for help) make your tool blend seamlessly into the user’s workflow.

When your tool feels like a natural part of the ecosystem, users will be far more likely to adopt it — and enjoy using it.

Other aspects

Beyond parameters and arguments, there are several other factors that distinguish a good CLI tool from a merely functional one. These aspects affect how your tool integrates with scripts, how users debug issues, and how easily it fits into larger workflows.

Exit codes

Every program returns an exit code when it finishes execution. This code lets the caller know whether the program succeeded or failed.

By convention:

  • 0 means success
  • Any non-zero value indicates an error

Although there’s no universal standard for exit codes, it’s good practice to at least exit with a non-zero code on any error.

For better consistency, consider following the conventions from the Advanced Bash-Scripting Guide. These are widely recognized in the Unix world.

You should also document your exit codes — include them in the --help output or the tool’s manual page. When users or automation systems understand what exit code 3 means, they can handle errors more intelligently (e.g., retry, skip, or alert).

STDOUT vs STDERR

A well-behaved CLI tool distinguishes between its two standard output streams:

  • STDOUT — for regular, expected output
  • STDERR — for errors, warnings, or diagnostic messages

This separation allows users and scripts to handle each stream independently. For instance, a user can redirect the normal output to a file while keeping error messages visible on the console:

mytool > output.txt

or suppress errors:

mytool 2>/dev/null

If your tool writes both data and errors to STDOUT, users will need to filter output manually — and that’s fragile.

Especially if your tool’s output is consumed by other programs, keeping STDOUT clean and predictable is essential.

Output format

If your tool produces data that might be consumed by other tools or scripts, it’s wise to support machine-readable output formats such as JSON or YAML.

For example:

mytool --output json

This makes automation much easier — other tools can use standard parsers instead of relying on brittle string parsing that breaks whenever spacing, alignment, or punctuation changes.

However, don’t sacrifice human readability. Many users will still run your tool interactively. The best approach is to:

  • Default to human-readable output (nicely formatted text)
  • Offer a flag (e.g. --json or --format if you want to support multiple formats) for structured output

Some CLI tools also provide auto-detection, sending pretty-printed text when writing to a terminal but JSON when piped into another process — similar to how kubectl or gh behave.

Error Messages

A good error message should be:

  • Clear — state what went wrong
  • Actionable — suggest how to fix it
  • Consistent — use the same tone and structure throughout

Bad example:

Error: failed

Better example:

Error: Could not open file '/tmp/input.txt' — file not found. Hint: Verify that the path is correct and you have read permissions.

Good error handling saves users time and helps them build trust in your tool.

Logging and Verbosity

Users appreciate control over how much information they see. A typical approach:

  • --quiet for minimal output
  • --verbose for detailed messages
  • --debug for developer-level tracing

Design your logging levels so users can choose the right amount of information for their context.

When combined with proper exit codes, these levels make debugging and automation much smoother.

Responsiveness and Performance

If your CLI performs heavy operations, consider providing progress indicators or spinners. For example:

Downloading files... 45% complete

Users shouldn’t have to wonder whether the program has hung. At the same time, avoid unnecessary animations or output when the tool is being run in non-interactive mode (e.g. as part of a script).

Conclusion

Building a CLI tool is relatively easy. Making a good one — that’s the real craft. A good command-line tool feels natural, behaves predictably, and quietly disappears into the user’s workflow. It doesn’t force users to adapt to it — it adapts to how users already work.

Throughout this article, we’ve looked at what contributes to that experience:

  • Clear and consistent parameters that balance simplicity and flexibility
  • Meaningful exit codes that communicate success or failure
  • Proper use of STDOUT and STDERR to separate data from diagnostics
  • Readable and structured output formats for both humans and machines
  • Helpful error messages and predictable behavior
  • Adherence to the conventions of your ecosystem, so your tool feels familiar from the first run

Ultimately, the best CLI tools share a common trait: they respect the user’s time. They start fast, fail fast, explain themselves clearly, and integrate seamlessly into larger systems and scripts.

If you keep these principles in mind — clarity, consistency, and empathy for your users — your CLI tool won’t just work; it’ll be a pleasure to use.

Disclaimer: The articles reposted on this site are sourced from public platforms and are provided for informational purposes only. They do not necessarily reflect the views of MEXC. All rights remain with the original authors. If you believe any content infringes on third-party rights, please contact [email protected] for removal. MEXC makes no guarantees regarding the accuracy, completeness, or timeliness of the content and is not responsible for any actions taken based on the information provided. The content does not constitute financial, legal, or other professional advice, nor should it be considered a recommendation or endorsement by MEXC.
Share Insights

You May Also Like

Astonishing Kevin Durant Bitcoin Fortune: A Decade-Long Hold Yields 195-Fold Return

Astonishing Kevin Durant Bitcoin Fortune: A Decade-Long Hold Yields 195-Fold Return

BitcoinWorld Astonishing Kevin Durant Bitcoin Fortune: A Decade-Long Hold Yields 195-Fold Return Imagine logging into an old account and discovering a fortune! That’s exactly what happened to NBA superstar Kevin Durant. His decade-old, forgotten Coinbase account, which held an early Kevin Durant Bitcoin investment, has now resurfaced, revealing an incredible 195-fold return. This remarkable story highlights the immense potential of long-term cryptocurrency holdings and serves as a fascinating example for anyone interested in digital assets. The Accidental ‘Hodl’: How Kevin Durant’s Bitcoin Investment Skyrocketed The journey of Kevin Durant’s Bitcoin investment began in 2016. He encountered Bitcoin, then priced at a modest $600, during a birthday celebration for venture capitalist Ben Horowitz. Intrigued, Durant decided to invest, setting up a Coinbase account. However, as many early adopters can attest, managing digital assets in the nascent crypto landscape wasn’t always straightforward. Durant subsequently misplaced his Coinbase login credentials, leading to an involuntary long-term hold – a phenomenon affectionately known as "HODL" (Hold On for Dear Life) in the crypto community. This accidental strategy proved to be a stroke of pure luck. After a decade, with assistance from Coinbase and a thorough identity verification process, Durant successfully recovered his account. While the exact amount of BTC remains undisclosed, the outcome is clear: a staggering 195-fold return on his initial investment. Initial Investment: Bitcoin at $600 in 2016. Accidental Strategy: Lost login details led to an unintentional "HODL." Recovery: Coinbase assisted with identity verification. Return: A remarkable 195-fold increase in value. Beyond Personal Gains: Kevin Durant’s Broader Crypto Engagement This isn’t Kevin Durant’s first foray into the world of digital assets, nor is it his only connection to the industry. Long before this incredible recovery, Durant had already demonstrated a positive and forward-thinking stance toward cryptocurrency. His engagement extends beyond just holding assets; he has actively participated in the crypto ecosystem. Durant previously partnered with Coinbase, one of the leading cryptocurrency exchanges, showcasing his belief in the platform and the broader potential of digital currencies. He has also ventured into the realm of Non-Fungible Tokens (NFTs), purchasing digital collectibles and exploring this evolving sector. These actions underscore his understanding and acceptance of crypto’s growing influence. His continued involvement helps bridge the gap between mainstream culture and the crypto world, bringing increased visibility and legitimacy to digital assets. The story of his Kevin Durant Bitcoin recovery only adds another layer to his impressive crypto narrative, inspiring many to consider the long-term prospects of digital investments. Valuable Lessons from Kevin Durant’s Bitcoin Journey Kevin Durant’s story offers compelling insights for both seasoned investors and newcomers to the crypto space. It powerfully illustrates the potential rewards of a patient, long-term investment approach, even if accidental. While not everyone will forget their login details for a decade, the principle of "HODLing" through market volatility can yield significant returns. However, it also subtly highlights the importance of proper security and record-keeping. Losing access to an account, even if eventually recovered, can be a stressful experience. Here are some actionable takeaways: Embrace Long-Term Vision: Bitcoin’s history shows substantial growth over extended periods. Patience often outperforms short-term trading. Secure Your Assets: Always keep your login details, seed phrases, and recovery information in multiple, secure locations. Consider hardware wallets for significant holdings. Understand the Volatility: Crypto markets are volatile. Investing only what you can afford to lose and being prepared for price swings is crucial. Stay Informed: While Durant’s hold was accidental, continuous learning about the crypto market can help make informed decisions. His experience reinforces the idea that strategic, even if involuntary, patience can be profoundly rewarding in the world of cryptocurrency. The Kevin Durant Bitcoin story is a testament to this. The tale of Kevin Durant’s forgotten Coinbase account and his astonishing 195-fold return on a decade-old Bitcoin investment is nothing short of extraordinary. It’s a vivid reminder of the transformative power of early adoption and the incredible growth potential within the cryptocurrency market. Beyond the personal windfall, Durant’s continued engagement with crypto, from partnerships to NFTs, reinforces his role as a prominent figure in the digital asset space. His accidental "HODL" has become a legendary example, inspiring many to look at long-term crypto investments with renewed optimism and a keen eye on future possibilities. Frequently Asked Questions About Kevin Durant’s Bitcoin Investment Here are some common questions regarding Kevin Durant’s recent crypto revelation: Q: How much did Kevin Durant initially invest in Bitcoin?A: The exact amount of Bitcoin Kevin Durant initially invested has not been disclosed. However, it was purchased around 2016 when Bitcoin was priced at approximately $600. Q: How did Kevin Durant recover his forgotten Coinbase account?A: Coinbase assisted Kevin Durant in recovering his account after he completed a thorough identity verification process, confirming his ownership of the decade-old account. Q: What does "195-fold return" mean?A: A "195-fold return" means that the value of his initial investment multiplied by 195 times. If he invested $1,000, it would now be worth $195,000. Q: Has Kevin Durant invested in other cryptocurrencies or NFTs?A: Yes, Kevin Durant has shown a friendly stance toward cryptocurrency beyond Bitcoin. He has partnered with Coinbase and has also purchased Non-Fungible Tokens (NFTs) in the past. Q: Is Kevin Durant’s story typical for Bitcoin investors?A: While the 195-fold return is exceptional, the principle of significant gains from long-term holding (HODLing) is a common theme in Bitcoin’s history. However, not all investments yield such high returns, and market volatility is always a factor. Did Kevin Durant’s incredible crypto journey inspire you? Share this astonishing story with your friends and followers on social media to spark conversations about the future of digital assets and the power of long-term investing! Your shares help us bring more fascinating crypto news to a wider audience. To learn more about the latest Bitcoin trends, explore our article on key developments shaping Bitcoin’s institutional adoption. This post Astonishing Kevin Durant Bitcoin Fortune: A Decade-Long Hold Yields 195-Fold Return first appeared on BitcoinWorld.
Share
Coinstats2025/09/19 18:45