CLI Speedtest (Rust)
A blazing-fast, high-performance CLI speedtest tool written in Rust. Designed for modern developers and system administrators who need accurate, machine-readable network performance metrics without the bloat.
Features
- Interactive Menu: User-friendly TTY menu for quick tests, settings, and help.
- Blazing Fast: Powered by
tokiofor asynchronous, non-blocking I/O. - High Concurrency: Multi-threaded download and upload tests using
tokiotasks andBarriersynchronization to saturate high-speed connections. - Production Grade:
- Warm-up Phase: Includes a 2-second warm-up period to avoid TCP slow-start bias for more consistent results.
- Retry Logic: Built-in exponential backoff for failed network requests.
- Comprehensive Metrics:
- Latency: Min, Max, Average, Jitter, and Packet Loss.
- Throughput: Real-time Mbps for both Download and Upload.
- Visual Polish: Semantic color-coding and live rolling-speed displays.
- Machine-Readable: Use the
--jsonflag for clean, parseable output perfect for cron jobs and monitoring. - Graceful Degradation: Automatically disables color and interactive features when piped or in non-TTY environments. Respects the
NO_COLORenvironment variable.
Installation
Using Cargo (Recommended for Rust Users)
If you have Rust installed, you can install the CLI easily:
Pre-compiled Binaries (GitHub Releases)
You can directly download and install the latest pre-compiled binaries from the terminal.
Linux (amd64):
macOS (Apple Silicon):
macOS (Intel):
Note for macOS Users: If you get a "command not found" error, ensure
/usr/local/binis in your$PATH. If macOS prevents the binary from running due to an "Unidentified Developer" warning (Gatekeeper), run:sudo xattr -d com.apple.quarantine /usr/local/bin/cli-speedtest
Windows (PowerShell):
Invoke-WebRequest -Uri "https://github.com/nazakun021/cli-speedtest/releases/latest/download/speedtest-windows-amd64.exe" -OutFile "cli-speedtest.exe"
# The executable will be available in your current directory as `cli-speedtest.exe`
From Source
You will need the Rust toolchain installed.
The binary will be available at target/release/cli-speedtest.
Usage
Interactive Mode
Simply run the installed binary without flags to enter the interactive menu:
Direct Run (Scripting Friendly)
Pass any configuration flag to bypass the menu and run directly:
| Flag | Description | Default |
|---|---|---|
-d, --duration <SECS> |
Length of the test in seconds | 10 |
-c, --connections <N> |
Number of parallel connections | 8 (DL), 4 (UL) |
--server <URL> |
Custom target server URL | Cloudflare |
--ping-count <N> |
Number of pings to send | 20 |
--no-download |
Skip the download test | - |
--no-upload |
Skip the upload test | - |
--json |
Output results in JSON format | - |
--no-color |
Disable terminal styling | - |
--debug |
Enable verbose logging | - |
--force-run |
Bypass the local cooldown and run immediately | - |
Examples
# Run a 5-second test with 12 connections
# Skip upload test and get JSON output
# Use a custom server
JSON Output Schema
When running with --json, the tool returns a structured object:
How It Works
Under the hood, cli-speedtest is built for maximum throughput and accuracy, utilizing Rust's powerful asynchronous ecosystem:
- Ping Phase: The tool sends lightweight HTTP requests to the target server to measure cold latency. It records minimum, maximum, average latency, and calculates jitter and packet loss.
- Download Phase: Spawns multiple concurrent
tokiotasks (default: 8) that independently stream chunks of data from the target server. A shared atomic counter tracks total bytes received in real-time. - Upload Phase: Spawns concurrent tasks (default: 4) that generate random, uncompressible payload data in-memory and POST them to the server. This guarantees that network compression doesn't skew the results.
- Warm-up Period: Before calculating the final speed, the engine discards the results from the first 2 seconds (the warm-up phase). This avoids TCP slow-start artifacts and ensures we're measuring the saturated connection speed.
- Real-time Engine: A periodic tick (e.g., every 100ms) polls the byte counters and calculates the rolling window throughput to display the live speed on your terminal.
Testing
The project includes unit tests for core logic and integration tests using mock servers (via mockito).
# Run all tests
# Run tests with logging enabled
RUST_LOG=debug
Project Structure
src/main.rs: Entry point and CLI routing logic usingclap.src/lib.rs: Core orchestration logic for ping, download, and upload phases.src/client.rs: High-concurrency network architecture usingtokioandreqwest.src/menu.rs: Interactive TTY menu and settings usingdialoguer.src/models.rs: Data structures and JSON serialization models.src/utils.rs: Technical constants (likeWARMUP_SECS) and measurement math.src/theme.rs: ANSI color system and UI rendering helpers.
Contributing
We welcome contributions! Whether it's adding new features, fixing bugs, or improving documentation, your help is appreciated.
Local Development Setup
-
Fork & Clone: Fork the repository on GitHub and clone your fork locally:
-
Build the Project: Compile the binary.
-
Run the Binary: Test your changes locally. You can use the
--debugflag for verbose output!
Code Style & Quality
Before submitting a pull request, please ensure your code adheres to standard Rust formatting and linting rules:
Submitting a Pull Request
- Create a new branch:
git checkout -b feature/your-feature-name - Commit your changes:
git commit -m "feat: add new awesome feature" - Push to your branch:
git push origin feature/your-feature-name - Open a Pull Request on GitHub!
License
Distributed under the Apache License 2.0. See LICENSE for more information.
Built with ❤️ by Tirso Benedict J. Naza