DEV Community

Cover image for How to create a CLI tool in Python
Muhammed Sabith
Muhammed Sabith

Posted on

How to create a CLI tool in Python

I've developed a CLI tool in python, here's how you can also

you can check out the github repository for more information : seta_link , also give a star ⭐ if you can

Requirements

1.python
2.Typer ( a module )

Idea

My idea for a CLI tool is a productivity timer, it is as simple as that. User can enter a command like seta start 5 and this starts a timer for 5 minutes. Here's how you can do that

Folder Structure

seta-timer/
├── pyproject.toml        # project metadata + CLI entry point
├── README.md             # optional
└── seta/                 # your package code
    ├── __init__.py
    └── __main__.py       # where the typer app lives

Enter fullscreen mode Exit fullscreen mode

the __init__.py is empty and is for there for python to treat it as an importable package.

In __main__.py we write the functions. So what should we write in pyproject.toml ?

Its role is to define how the project is built, packaged, and its metadata.

what to put inside pyproject.toml ?

[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "seta"
version = "0.1.0"
dependencies = ["typer", "plyer"]

[project.scripts]
seta = "seta.__main__:main"

Enter fullscreen mode Exit fullscreen mode

you can change the name , version and can add extra dependencies if needed. For now we need typer and plyer

if you want to change the command name, (for example, if you want alexa start 5) you can do the following: (change the command name)

[project.scripts]
<command-name> = "<module-path>:<callable>"

Enter fullscreen mode Exit fullscreen mode

typer is for creating CLI tool
and plyer is for sending notification in your device

Real Programming Part

Now we're going to write the necessary functions inside our __main__.py. Here's the code I've written:

import time
import typer
from plyer import notification

app = typer.Typer()


@app.command()
def start(minutes: int = typer.Argument(..., help="Duration in minutes")):
    seconds = minutes * 60
    typer.echo(f"Timer for {minutes} minutes has started...")

    while seconds:
        mins, secs = divmod(seconds, 60)
        timeformat = f"{mins:02d}:{secs:02d}"
        print(timeformat, end="\r")
        time.sleep(1)
        seconds -= 1

    notification.notify(
        title="⏰ Timer Done",
        message=f"{minutes} minute(s) finished!",
        timeout=10, toast=True
    )
    typer.echo("✅ Time is up!")


@app.command()
def version():
    """Show version information."""
    typer.echo("seta v0.1.0")


def main():
    app()


if __name__ == "__main__":
    main()
Enter fullscreen mode Exit fullscreen mode

An extra function (def version) is also called out, otherwise with only one functionality the tool won't work as we expected

Explanation of the code

It accepts a command ( seta start 5) for starting a timer for 5 minutes, seconds is got by multiplying minute by 60. The while loop runs until the seconds become 0 (It's job is to decrease the second by 1 and also print the remaining time on the same line). When the timer ends, we get a notification in our device (make sure to turn on notifications)

After you're satisfied with the functionalities you can run the following command to install this globally in your device :

pip install -e .
Enter fullscreen mode Exit fullscreen mode

After installing go to cmd or terminal and run the following command to see if it's working or not :

seta start 5
Enter fullscreen mode Exit fullscreen mode

this starts a timer for 5 minutes and notifies you at the end.

Now What ???

Now you can add more functionalities to make it super useful, or you can build another one for automating your tasks, if you want to star ⭐ seta check out seta-timer.

all sorts of contributions are accepted !
Also ask any doubts you've ❤️‍🔥❤️‍🔥❤️‍🔥

Top comments (3)

Collapse
 
developeraromal profile image
Aromal

That's definitely a great tutorial to start a cli tool from scratch, I will definitely star this repo keep posting more contents like this

Collapse
 
masterdevsabith profile image
Muhammed Sabith

thanks ! I'll be definitely posting more of these

Collapse
 
masterdevsabith profile image
Muhammed Sabith

Sure