A few days ago, I had a simple idea:
What if I could type internetspeed in the terminal, press Enter, and instantly see my internet speed and public IP?
That tiny thought turned into a real project, a GitHub repository, an installable Python CLI, and eventually a PyPI package that anyone can install with:
pip install internetspeed
Git Repo: https://github.com/cranky420/internetspeedtest.git
This post is about how I built it, what broke along the way, why open source matters, and what I learned from turning a local Python script into a real distributable tool.
Why I started this
I wanted something that felt as natural as Linux commands like:
date
pwd
ls
I started with a local Python script that did three things:
- fetched my public IP
- measured download speed
- measured upload speed
The first version wasn’t elegant. It was just about proving the idea.
I used requests to fetch the public IP from a public API, then used a test function to measure network throughput.
That gave me the first “it works” moment.
And that matters a lot. In open source, people often jump too quickly to packaging, publishing, branding, and documentation. But the real first step is always the same:
Make one small thing work.
Turning a script into a CLI
!Image description(https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qlk6vhoms7cb6xlh2h2d.png)
That sounds small, but it changes everything.
A real CLI feels like software.
A script feels like a file.
My project started to look more like a proper CLI application instead of a personal script.
Here is the general shape of the command:
import click
from rich import print
from speed import test_speed
And then the command itself:
@click.command()
def cli():
print("[cyan]Running internet test...[/cyan]")
result = test_speed()
print()
print(f"[green]Download:[/green] {result['download']} Mbps")
print(f"[green]Upload:[/green] {result['upload']} Mbps")
print(f"[green]IP:[/green] {result['ip']}")
That’s when it started feeling real.
The folder structure that made it clean
I began with a messy folder, like many first projects do. But once I wanted to publish it, I needed a cleaner structure.
My repo eventually looked like this:
internetspeedtest/
├── cli.py
├── speed.py
├── setup.py
├── README.md
├── requirements.txt
├── LICENSE
├── CONTRIBUTING.md
├── .gitignore
└── venv/
How the package became installable
The real transformation happened when I made the project installable as a command-line tool.
That meant adding setup.py and defining a console entry point.
Here is the essential idea:
from setuptools import setup
This tells Python packaging:
- the project name is internetspeed
- it has dependencies
- and the terminal command should be internetspeed
After installing the package in editable mode:
pip install -e .
I could run:
internetspeed
That was a huge milestone.
It meant the project was no longer just code in a folder. It was software with an interface.
I learned about:
- API tokens
- twine
- trusted publishing
- package naming
- distribution builds
- GitHub Actions workflows
At first, I got 403 errors. Later, I realized it was just a credential flow issue.
That kind of debugging is part of open source too. A project becomes real when you learn how to ship it, not just how to write it.
Publishing to PyPI
This was the moment the project became global.
Once the package was built properly, I could upload it to PyPI and make it available to anyone.
That means anyone can now do:
pip install internetspeed
and then:
internetspeed
That’s a massive shift.
A local repo became a public tool.
That is one of the most satisfying parts of software development: turning something personal into something shareable.
Why open source matters here
I did not want this to be a closed personal tool.
I wanted it to be open source because open source turns software into a conversation.
Once a repo is public, other people can:
- inspect the code
- report bugs
- suggest improvements
- add features
- fix packaging
- improve documentation
- adapt it for their own workflow
That is powerful.
What I added to make it contributor-friendly
If you want other people to help, you need to make the project welcoming.
That means adding things like:
README.md
This explains what the project does, how to install it, and how to use it.
CONTRIBUTING.md
This tells people how to participate.
Clean Git history
Small, clear commits are easier to review and understand.
Open source does not start with “welcome contributors.”
It starts with making the project readable.
What internetspeed actually solves
At first glance, this may look like a tiny utility. But it solves a real workflow problem.
Sometimes you want to check:
- your download speed
- your upload speed
- your public IP
- whether a connection is behaving correctly
What I actually learned was this:
Open source is not just code. It is packaging, documentation, publishing, maintenance, debugging, and community design.
That was the biggest lesson.
A project becomes open source only when someone else can realistically use it, understand it, and contribute to it.
The long-term vision is to make it easy for anyone to check and observe their network speed from the terminal, and maybe even use it as part of a larger monitoring workflow.
Top comments (0)