Usage
Quickstart (Windows / PowerShell)
$root = "$env:USERPROFILE\Rust-Crates"
New-Item -Force -ItemType Directory $root, "$root\crates.io-index", "$root\mirror" | Out-Null
# First-time clone of the index
git clone https://github.com/rust-lang/crates.io-index "$root\crates.io-index"
# Build the CLIs
go build -o .\bin\download-crates.exe .\cmd\download-crates
go build -o .\bin\generate-sidecars.exe .\cmd\generate-sidecars
# Dry-run preflight — validates config, estimates work, downloads nothing
.\bin\download-crates.exe -index-dir "$root\crates.io-index" -out "$root\mirror" -concurrency 256 -dry-run -log-level info
# Real run, with metrics on :9090
.\bin\download-crates.exe -index-dir "$root\crates.io-index" -out "$root\mirror" -concurrency 256 -include-yanked -progress-interval 5s -listen :9090 -log-format json
Metrics: http://localhost:9090/metrics · Status: http://localhost:9090/api/status
The Python wrapper (Clone-Index.py)
The wrapper is the simpler entry point — it clones/updates the index and invokes the downloader for you:
python Clone-Index.py --index-dir "A:\rust-lang\crates.io-index" --output-dir "A:\rust-lang\crates\" --include-yanked --logpath "A:\rust-lang"
Key flags: --threads (maps to -concurrency, default 128), --verify-existing (re-hash and verify existing files instead of trusting them), --bundle / --bundle-mode {only,add} / --bundle-size-gb (rolling archive output), --manifest (JSONL audit log path), --listen (metrics address, default :9090), --dry-run.
Several flags (--rate-limit, --resume, --verify) are kept only for backward compatibility and no longer do anything distinct — the Go downloader now owns retry/resume/verification behavior directly.
Airgap transport workflow
CloneCratesio's manifest + bundle design exists specifically to support moving a verified crate set into an environment with no network access:
- Download with a manifest — every run emits
manifest.jsonlwithpath,size,sha256,yanked, andtimestampfor each crate. - Bundle for transport (optional) — add
-bundle -bundles-out /data/crates-bundlesto roll files into.tar.zstarchives, reducing inode count and copy time. - Generate sidecars —
generate-sidecarsproduces per-crate metadata for downstream tooling. - Verify before transport:
jq -r 'select(.ok==true) | "\(.sha256) \(.path)"' manifest.jsonl > checksums.txtsha256sum -c checksums.txt
- Move the mirror or bundle archives + manifest using
robocopy(Windows) orrsync(Linux) to preserve timestamps and retry on transient errors. - Re-verify offline — recompute hashes on arrival, spot-check a random sample, and confirm sidecar files match expected index metadata.
Performance notes
- Use NVMe storage; avoid mirroring onto network shares.
- Consider disabling NTFS compression on the output directory for better throughput.
- Resume is automatic — existing verified files are skipped via checksum/size checks, so re-running a mirror is cheap.