For those creating their own CLI tool
If you have played around with any command line interface tools, such as Particle CLI or Git UI, you’ll notice that they oftentimes will have a verbose or -v option with their commands. This allows you to change log levels within the program, outputting as little or as much as you desire.
This example CLI tool makes use of the Click library for Python. If you are having trouble getting started, check out my first blog on making a professional-looking CLI tool or Click’s documentation.

Why is it Important to Have a Verbose Option?
When using your CLI tool, users may have a variety of reasons for wanting to change how much information is displayed.
If a user is debugging a process or needs to know a little more about the error being thrown, they may want to use the verbose option to dump out more logs and information to nail down their issue.
On the other hand, a user may just want to be quickly using the CLI commands and does not want or need to see the multitudes of code on every successful run. Some users may not have a firm grasp on functionality behind your CLI tool and it’ll look messy and confusing to them.
Logging Levels
Here’s how ‘cool_logger’ was set up in mysupercoolscript from the last blog post.
First off, click.option is added. This will add the option ”verbose or -v. Both of these options will dump out the same log, one just being longer and the other quicker to type out. Secondly, we want to edit the mysupercoolscript definition. Before, the only parameter was self. Now, it will take in the parameters self and verbose. Then, the if/else statement will set the log level to either DEBUG or INFO depending on if the verbose option was given or not.
@click.group()
@click.option('--verbose', '-v', is_flag=True, help="Will print more logging messages.")
@click.pass_context
def mysupercoolscript(self, verbose):
if verbose:
cool_logger.setLevel(logging.DEBUG)
else:
cool_logger.setLevel(logging.INFO)
pass
The next step and easiest way to implement the verbose option is to set logging levels. If you are a bit confused on how python’s logging works, lay your confusion to rest here. This is in “main” in mysupercoolscript.py file, which you can find a link to at the bottom of this post.
import logging
cool_logger = logging.getLogger('cool_logger')
cl = logging.StreamHandler()
cl.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(message)s')
cl.setFormatter(formatter)
cool_logger.addHandler(cl)
Adding the above code snippit with your own logger name (or you could keep cool_logger) will initialize your logger. Now, we need to add a bit to our main function in mysupercoolscript.py to allow the option to work. In the initialization of our group, we will add:
Now on to the final piece of the puzzle. Instead of using the print or another function, we will use cool_logger.debug and cool_logger.info based on when we want our information printed. With the current setup, when you want something printed all the time, you want to use cool_logger.info. When you want a line to print only when the verbose option is used, you want to use cool_logger.debug.
Where and When Should I Use Different Levels
Now Python’s logger actually has six different levels for you to utilize, but we’ll only be showing off two of them: DEBUG and INFO.
Here at Dojo Five, we try to keep our CLI tool’s logger to a guideline so we keep it nice and tidy. However depending on the scope and complexity of your project it may make sense to add additional levels for added clarity in logs.
Generally, try keeping your reporting short and sweet, especially on successful runs. Only mention important parts, and be descriptive but short.
For failures, we will want to give one error line. It should be short and to the point, but readable.
For example, say you have a command build that compiles a script, then stores the output into a folder named outputs.
Running build may yield:
Compiled Successfully.
ERROR: Output not stored.
Message: Directory outputs not found
Whereas if you ran build –verbose, it may yield a more-inclusive:
Building test.cpp...
Building test2.cpp...
WARNING: Variable A is delcared but not used.
Compiled Successfully.
Error during output stage:
ERROR: Output not stored.
Directory: outputs not found.
Output files will not be saved.
The Dry Stuff (Code)
Just in case you’re a bit confused about how everything is being implemented, you can find the source code for these examples on gitlab: source code.
There you can find both setup.py and supercoolscript.py
What are some things you’re struggling with on your CLI? Feel free to reach out if you would like help. Good luck with your future CLI endeavors!If you have questions about an embedded project you’re working on, Dojo Five can help with all aspects of your devops for embedded journey! We are always happy to hear about cool projects or interesting problems to solve. Bring your interesting problems that need solving – we are always happy to help out. You can book a call with us to get the conversation started. We look forward to hearing from you!
Sign up to get our content updates!
Unlock the full potential of your embedded projects with our expert insights! Dive into our comprehensive resources to stay ahead in firmware development. Subscribe now to get the latest best practices and guides delivered straight to your inbox.
Sign Up for Updates


