A production-grade, resilient CLI speedtest tool written in Rust. Designed for modern developers and system administrators who need accurate, machine-readable network performance metrics without the bloat—optimized for reliability against public infrastructure.
- Interactive by Default: User-friendly TTY menu for manual tests and settings. It shows the selected mode, duration, connections, ping probes, and Cooldown state before a test. Automatically switches to Direct Mode for measurement and execution flags or in non-TTY environments.
- Resilient Network Engine:
- Provider-Friendly Design: Built-in 5-minute local cooldown for standard runs. Quick Mode bypasses Warm-up and the standard Cooldown for up to five successful Quick Burst runs.
- Anti-Ban Hardening: Implements User-Agent rotation and request pacing (jitter) to ensure consistent connectivity.
- Adaptive Fallback: Retries an affected throughput phase with one connection when rate-limited; the Provider can still reject that retry.
- Production Grade Accuracy:
- Warm-up Phase: Discards the first 2 seconds of transfer data to avoid TCP slow-start bias (bypassed in Quick Mode).
- High Concurrency: Multi-threaded engine using
tokiotasks andBarriersynchronization to saturate high-speed links.
- Comprehensive Metrics:
- Latency: Min, Max, Average, Jitter, and Packet Loss.
- Throughput: Real-time Mbps for both Download and Upload.
- Self-Update: Checks for updates on interactive startup at most once every 24 hours, prompts for confirmation, verifies the downloaded binary with SHA-256, and performs an in-place replacement.
- Visual Polish: Semantic color-coding (Mbps/Ping thresholds) and live rolling-speed displays.
- Machine-Readable: Use the
--jsonflag for clean, parseable output perfect for cron jobs and monitoring.
If you have Rust installed, you can install the CLI easily:
cargo install cli-speedtestYou can directly download and install the latest pre-compiled binaries from the terminal.
Each published binary has an adjacent .sha256 file. Compare its SHA-256 value with the downloaded binary before executing it when integrity verification is required.
Linux (amd64):
curl -L https://github.com/nazakun021/cli-speedtest/releases/latest/download/speedtest-linux-amd64 -o cli-speedtest
chmod +x cli-speedtest
sudo mkdir -p /usr/local/bin
sudo mv cli-speedtest /usr/local/bin/macOS (Apple Silicon):
curl -L https://github.com/nazakun021/cli-speedtest/releases/latest/download/speedtest-macos-arm64 -o cli-speedtest
chmod +x cli-speedtest
sudo mkdir -p /usr/local/bin
sudo mv cli-speedtest /usr/local/bin/macOS (Intel):
curl -L https://github.com/nazakun021/cli-speedtest/releases/latest/download/speedtest-macos-intel -o cli-speedtest
chmod +x cli-speedtest
sudo mkdir -p /usr/local/bin
sudo mv cli-speedtest /usr/local/bin/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`You will need the Rust toolchain installed.
git clone https://github.com/nazakun021/cli-speedtest.git
cd cli-speedtest
cargo build --releaseThe binary will be available at target/release/cli-speedtest.
Simply run the installed binary without flags to enter the interactive menu for manual checks:
cli-speedtestThe main menu distinguishes a Configured Test from a one-off Quick Test. Quick Mode skips Warm-up, so it provides a faster estimate and consumes one successful run from the five-test Quick Burst limit. Commands and the results guide use a compact unboxed layout on narrow terminals.
Pass a measurement or execution flag to bypass the menu and run directly. Direct Mode is optimized for scripting and automation:
| Flag | Description | Default |
|---|---|---|
-d, --duration <SECS> |
Length of the test in seconds | 10 |
-c, --connections <N> |
Number of parallel connections | 4 (DL), 2 (UL) |
--server <URL> |
Custom Provider base URL; selected endpoints are preflighted | 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 | - |
--quick |
Fast estimate; bypasses Warm-up and standard Cooldown within the five-run Quick Burst limit | - |
--self-update |
Check for updates and install latest immediately | - |
You can configure the tool using the following environment variables:
| Variable | Description |
|---|---|
NO_COLOR |
Disables ANSI terminal styling/coloring (also honors the standard NO_COLOR env var). |
NO_UPDATE or CLI_SPEEDTEST_NO_UPDATE |
Disables automated background update checks on startup. |
# Run a 5-second test with 12 connections (Bypasses auto-defaults)
cli-speedtest --duration 5 --connections 12
# Skip upload test and get JSON output for monitoring
cli-speedtest --no-upload --json
# Use a custom server
cli-speedtest --server https://your-custom-speedtest-server.comWhen running with --json, the tool returns a structured object. Note that latency limits min_ms and max_ms are integers (u128). Throughputs download_mbps and upload_mbps are optional and will be completely omitted from the JSON output if their respective tests are skipped (e.g., via --no-download or --no-upload).
{
"timestamp": "2026-04-05T12:00:00Z",
"version": "0.1.5",
"server_name": "Cloudflare",
"ping": {
"min_ms": 10,
"max_ms": 25,
"avg_ms": 15.1,
"jitter_ms": 2.3,
"packet_loss_pct": 0.0
},
"download_mbps": 450.2,
"upload_mbps": 120.5
}cli-speedtest is built on standard HTTP primitives, optimized for the Cloudflare infrastructure but designed for future provider extensibility:
- Ping Phase: Measures latency using lightweight
GET /cdn-cgi/tracerequests. Calculates min, max, average, jitter, and packet loss. - Download Phase: Spawns concurrent
tokiotasks that stream chunks from the provider. Implements request pacing to break machine-like patterns. - Upload Phase: Generates random, uncompressible payload data in-memory and POSTs to the provider, ensuring network compression doesn't skew throughput results.
- Resiliency Layer: If the provider returns a rate-limit signal (HTTP 429), the engine fails fast with clear guidance or automatically falls back to a single-connection retry if appropriate.
- Warm-up Period: Discards results from the first 2 seconds (the warm-up phase) to ensure measurements reflect saturated connection speeds, not TCP slow-start artifacts.
- Real-time Engine: A periodic tick polls atomic byte counters to display live rolling-window throughput.
The project includes unit tests for core logic and integration tests using mock servers (via mockito).
# Run all tests
cargo test
# Run tests with logging enabled
RUST_LOG=debug cargo testStart with docs/README.md for the documentation map. Operational behavior, local state, automation guarantees, and measurement limits are in docs/OPERATIONS.md. Release history is in CHANGELOG.md.
src/main.rs: Entry point and CLI routing; manages User-Agent rotation and global timeouts.src/lib.rs: Core orchestration logic and adaptive concurrency fallback.src/client.rs: High-concurrency network architecture and request pacing (jitter).src/cooldown.rs: Disk-persisted local cooldown enforcement.src/updater.rs: Performs GitHub release checking, checksum validation, and self-updating.src/menu.rs: Interactive TTY menu and settings.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.
We welcome contributions! Whether it's adding new features, fixing bugs, or improving documentation, your help is appreciated.
- Fork & Clone: Fork the repository on GitHub and clone your fork locally.
- Build the Project:
cargo build - Run the Binary:
cargo run -- --debug
cargo fmt # Auto-format your code
cargo clippy # Run the linter
cargo test # Ensure all tests passThis project is dual-licensed under the MIT and Apache 2.0 licenses. See LICENSE-MIT and LICENSE-APACHE for more information.
Built by Tirso Benedict J. Naza