Updates & Telemetry
Updating
Section titled “Updating”sparkrun updateThis upgrades sparkrun itself (if it was installed via uv) and then always
refreshes your recipe registries from git. sparkrun setup update is the same
command under its full name.
If sparkrun was installed some other way — pip, pipx, or an editable
checkout — the self-upgrade step is skipped and only registries are updated.
Release channels
Section titled “Release channels”sparkrun tracks three channels. With no flag, sparkrun update stays on your
current channel; passing a flag switches to that channel and updates.
| Channel | Flag | Source |
|---|---|---|
| Stable | --stable | PyPI releases |
| Beta | --beta | the develop branch |
| Alpha | --alpha (or --yolo) | the develop-next branch |
sparkrun update --beta # switch to beta and updatesparkrun update # stay on beta from now onsparkrun update --stable # switch backThe channel also drives feature-flag defaults — a
capability can be on by default for alpha while staying off for stable. You
can preview another channel’s feature set without changing which code you run
by setting features.channel in config.yaml.
Anonymous telemetry
Section titled “Anonymous telemetry”sparkrun collects anonymous usage telemetry, and it is enabled by default. It carries no hostnames, addresses, credentials, or recipe names — see what is collected for the full list, including the one field that can identify your work.
Turning it off
Section titled “Turning it off”For a single command, without touching config:
SPARKRUN_NO_TELEMETRY=1 sparkrun run my-recipePrefer this when only some of your runs are sensitive — the rest still contribute the signal the project relies on.
To opt out persistently:
sparkrun setup telemetry --disable # persist the opt-outsparkrun setup telemetry # show the current settingsparkrun setup telemetry --enable # turn it back onThe environment variable is the single per-process override and beats the
persisted setting either way — a truthy value opts out, a falsy value forces it
on. So SPARKRUN_NO_TELEMETRY=0 re-enables telemetry for one command even when
it is disabled in config. The persisted setting lives at telemetry.enabled in
~/.config/sparkrun/config.yaml.
What is collected
Section titled “What is collected”Four event types are emitted: run, benchmark, update, and
setup_wizard. Each carries a random installation ID plus:
- OS name, OS release, and CPU architecture.
- The model identifier from the recipe — but only when it is a repo confirmed publicly readable on HuggingFace (see below) — plus a quantization/dtype summary.
- Runtime, executor, and scheduler names; success/return code; duration; whether the run was solo or a dry run.
- Cluster shape — node count, total GPU count, and accelerator vendor/model counts. Not hostnames or addresses.
- How the recipe was referenced, classified into
spark_arena/url/file/reference— not the recipe name, path, or URL. - Registry counts (total, enabled, non-default) — not registry names or URLs.
- For updates: old/new version, channel, and whether the self-upgrade succeeded. For the wizard: which steps were opted into, skipped, or failed.
Hostnames, IP addresses, SSH usernames, recipe names and paths, registry names, and registry URLs are not sent. Emission is best-effort with a sub-second timeout, so it never delays or fails a command.
Model identifiers
Section titled “Model identifiers”The model name is the one field that could describe your work, so it is filtered rather than sent as written. The raw value leaves your machine only when the repo is confirmed publicly readable on HuggingFace. Otherwise it is replaced with a coarse placeholder that records why it was withheld, without naming anything:
| Sent | When |
|---|---|
Qwen/Qwen3-1.7B | The repo is public — the signal the project actually wants |
<hf-private> | The repo is private or gated |
<local-path> | The model is a path to weights on local disk |
<unknown-visibility> | Visibility could not be established |
Visibility comes from the Hub’s own private / gated flags, not from whether
a lookup succeeded. That distinction matters: if you have an HF_TOKEN
configured, your private repos resolve perfectly well, so “it fetched” would
have been the wrong test.
The check fails closed. Offline, rate-limited, a typo’d repo id, or a run
where model detection was skipped all yield <unknown-visibility> rather than
the name — being unable to check is never treated as permission to send.
Local paths are classified without contacting the Hub at all.