buffr — privacy
Two opt-in surfaces — telemetry counters and the crash reporter — are both off by default and both local-only. buffr never sends usage or crash data to a network endpoint. Not now, not ever, not even to a kryptic-owned server. The implementation is a deliberate no-op that documents the design rather than a stub waiting for an endpoint.
There is one network request buffr makes by default — see Update channel below. It can be disabled.
Update channel — one HTTP GET per day
Default-on. [updates] enabled = true in the user config. buffr makes one
HTTP GET per check_interval_hours (default 24 h) against
https://api.github.com/repos/kryptic-sh/buffr/releases/latest. The request
carries no PII: only a User-Agent: buffr/<version> header (which GitHub
mandates) and an Accept: application/vnd.github+json header. No cookies, no
auth token, no telemetry payload. GitHub logs the request like any public API
request (IP + timestamp); buffr does not run its own collector.
To disable entirely, set [updates] enabled = false in config.toml. That path
makes zero network calls — the --check-for-updates CLI flag short-circuits
without opening a socket. See Updates for the full surface.
Telemetry — opt-in usage counters
Off by default. Set [privacy] enable_telemetry = true in config.toml to opt
in. When enabled, buffr writes anonymous integer counters to:
~/.local/share/buffr/usage-counters.json
The data directory is XDG-everywhere — the same ~/.local/share/buffr/ on
Linux, macOS, and Windows ($XDG_DATA_HOME is honored on every platform). Debug
builds use buffr-debug instead of buffr.
The file is pretty-printed JSON. After one app start it looks like:
{
"app_starts": 1
}
Counters tracked:
| Key | Increments on |
|---|---|
app_starts | Successful CEF init. |
tabs_opened | Every BrowserHost::open_tab (foreground + background). |
pages_loaded | Every main-frame LoadHandler::on_load_end. |
searches_run | Omnibar input that falls through to the search-engine route. |
bookmarks_added | :bookmark cmdline (Netscape import is intentionally not). |
downloads_completed | DownloadHandler reports is_complete(). |
Counters flush every 60 s in the background plus once at clean shutdown. There is no code path that opens a network socket for telemetry — there is no endpoint to disable, no opt-out flag to flip; the network surface simply does not exist.
If you want to share counters with someone, write a script that reads the JSON
and curls it to wherever you choose. buffr will not do this for you.
CLI:
buffr --telemetry-status # print enabled/disabled, path, and current counts
buffr --reset-telemetry # truncate counters to {}
--private mode forces telemetry off regardless of the config flag — the whole
point of --private is "leave no traces".
Crash reporter — opt-in local panic capture
Off by default. Set [crash_reporter] enabled = true to opt in. When enabled,
buffr installs a std::panic::set_hook that captures the panic message,
panic-site location, and a Backtrace::force_capture (always on, regardless of
RUST_BACKTRACE) and writes a JSON report to:
~/.local/share/buffr/crashes/<RFC3339-timestamp>_<seq>.json
Filename pattern: YYYY-MM-DDTHH-MM-SS.sssZ_<N>.json — colons swapped for
dashes so the path is portable to FAT/Windows, plus a process-wide counter. The
timestamp is only millisecond-precise, so the counter (and an O_EXCL-style
create_new open with retry) keeps two threads that unwind in the same
millisecond from overwriting each other's report.
CEF's BrowserProcessHandler does not expose an on_uncaught_exception
callback in the libcef buffr links (152.0.6, via the cef crate 152.x) —
the only on_uncaught_exception is on the renderer- process
RenderProcessHandler and only fires for V8 exceptions (JavaScript errors).
Native CEF crashes are caught by Chromium's internal crashpad/ breakpad
pipeline, which buffr does not currently configure (it requires a
crashpad_handler binary plus a symbol-server URL — both Phase 7 work). Phase 6
ships the panic-hook reporter only.
Reports are kept locally. Inspect them by hand:
buffr --list-crashes # one line per report: <ts>\t<version>\t<location>\t<msg>
buffr --purge-crashes # delete reports older than crash_reporter.purge_after_days
If you want to send a report to someone, mail the JSON file. buffr never uploads.