A minimal, lightweight crate update checker for Rust CLI applications.
Existing update checker crates add significant binary bloat:
| Crate | Binary Impact |
|---|---|
| tiny-update-check | ~0.5MB |
| update-informer | ~1.4MB |
| updates | ~1.8MB |
This crate achieves minimal size by:
- Using
native-tls(system TLS) instead of bundling rustls - Minimal JSON parsing (string search instead of serde)
- Simple file-based caching
[dependencies]
tiny-update-check = "1"For pure-Rust TLS (larger binary, but better cross-compilation):
[dependencies]
tiny-update-check = { version = "1", default-features = false, features = ["rustls"] }use tiny_update_check::check;
fn main() {
// Check at end of your CLI's main function
if let Ok(Some(update)) = check(env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")) {
eprintln!("Update available: {} -> {}", update.current, update.latest);
}
}use tiny_update_check::UpdateChecker;
use std::time::Duration;
fn main() {
let checker = UpdateChecker::new(env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"))
.cache_duration(Duration::from_secs(60 * 60)) // 1 hour cache
.timeout(Duration::from_secs(10)); // 10 second timeout
match checker.check() {
Ok(Some(update)) => {
eprintln!("New version {} available!", update.latest);
eprintln!("You have version {}", update.current);
}
Ok(None) => {} // Already on latest
Err(e) => {
// Silently ignore errors - don't disrupt the user's workflow
log::debug!("Update check failed: {}", e);
}
}
}use tiny_update_check::UpdateChecker;
use std::time::Duration;
let checker = UpdateChecker::new("my-crate", "1.0.0")
.cache_duration(Duration::ZERO); // Always fetch freshuse tiny_update_check::UpdateChecker;
use std::path::PathBuf;
// Use a custom cache directory
let checker = UpdateChecker::new("my-crate", "1.0.0")
.cache_dir(Some(PathBuf::from("/tmp/my-cache")));
// Or disable caching entirely
let checker = UpdateChecker::new("my-crate", "1.0.0")
.cache_dir(None);By default, pre-release versions (e.g., 2.0.0-alpha.1) are excluded from update
checks. Opt in to receive pre-release notifications:
use tiny_update_check::UpdateChecker;
let checker = UpdateChecker::new("my-crate", "1.0.0")
.include_prerelease(true);Enable the async feature for async applications:
[dependencies]
tiny-update-check = { version = "1", features = ["async"] }
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }use tiny_update_check::r#async::UpdateChecker;
#[tokio::main]
async fn main() {
let checker = UpdateChecker::new("my-crate", "1.0.0");
if let Ok(Some(update)) = checker.check().await {
eprintln!("Update available: {} -> {}", update.current, update.latest);
}
}| Feature | Default | Description |
|---|---|---|
native-tls |
✅ | Uses system TLS libraries, smaller binary |
do-not-track |
✅ | Respects the DO_NOT_TRACK environment variable |
rustls |
Pure Rust TLS, no system dependencies | |
async |
Async support using reqwest |
|
response-body |
Includes the raw crates.io response body in UpdateInfo |
You can attach a message to update notifications by hosting a plain text file at a URL:
use tiny_update_check::UpdateChecker;
let checker = UpdateChecker::new("my-crate", "1.0.0")
.message_url("https://example.com/my-crate-update-message.txt");
if let Ok(Some(update)) = checker.check() {
eprintln!("Update available: {} -> {}", update.current, update.latest);
if let Some(msg) = &update.message {
eprintln!("{msg}");
}
}The message is fetched only when an update is available. If the fetch fails, the
update check still succeeds with message set to None.
Enable the response-body feature to access the full crates.io API response:
[dependencies]
tiny-update-check = { version = "1", features = ["response-body"] }This adds a response_body: Option<String> field to UpdateInfo, letting you
extract any field from the crates.io response using your own parsing logic.
The Error enum covers all failure modes:
| Variant | Cause |
|---|---|
HttpError |
Network or HTTP request failure |
ParseError |
Failed to parse crates.io response JSON |
VersionError |
Invalid semver version string |
CacheError |
Cache file I/O failure |
InvalidCrateName |
Crate name fails validation (empty, too long, invalid characters) |
Update checks are designed to fail gracefully — errors should typically be logged and ignored so they don't disrupt the user's workflow.
- Checks cache file (in platform cache directory) for recent version info
- If cache is stale (default: 24 hours), queries crates.io API
- Compares versions using semver
- Returns
Some(UpdateInfo)if newer version exists
Cache locations by platform:
- Linux:
$XDG_CACHE_HOME/<crate>-update-checkor$HOME/.cache/<crate>-update-check - macOS:
$HOME/Library/Caches/<crate>-update-check - Windows:
%LOCALAPPDATA%\<crate>-update-check
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
at your option.