Telemetry & Privacy¶
mauto collects nothing unless you turn telemetry on. This page describes
what it would collect if you did, exactly, field by field.
The short version¶
- Off by default. No prompt, no banner, no opt-out flow — you turn it on or it stays off.
- No free text of any kind ever leaves your machine: no scenario ids, app package names, device serials, element labels, typed input or filesystem paths.
- No per-machine identifier. There is no install id, no device fingerprint and no user id. Events are anonymous and uncorrelated.
- Everything is spooled to a local file first. You can read it before it goes:
cat mobile-automator/.logs/telemetry.spool.
Turning it on and off¶
mauto telemetry status # what is on, what would be sent, what is queued
mauto telemetry enable # opt in
mauto telemetry disable # opt back out
mauto telemetry flush # upload what is queued now
mauto telemetry enable writes telemetry.enabled: true into
mobile-automator/config.json. mauto config set telemetry.enabled true does
the same thing.
Two environment variables override the config and always win:
| Variable | Effect |
|---|---|
MAUTO_TELEMETRY=0 |
Disables telemetry regardless of config. |
DO_NOT_TRACK=1 |
Disables telemetry regardless of config. |
MAUTO_TELEMETRY=1 deliberately does not enable telemetry. An off-switch is
safe to honour from the environment; an on-switch is a way to turn collection on
for a machine — a CI image, a shared shell profile, an inherited Dockerfile —
whose owner never consented to it. Opting in happens in a file the project owner
edits.
Two further environment variables can redirect where enabled telemetry is
sent: MAUTO_TELEMETRY_HOST (default eu.i.posthog.com) and
MAUTO_TELEMETRY_TOKEN. They exist for self-hosters pointing an enabled project
at their own instance, and they do nothing while telemetry is off — there is
nothing to redirect. Neither can turn collection on.
What is sent¶
These are the only fields that can ever cross the network. The list is enforced
by src/observe/event.js, which builds the payload by iterating this catalog
rather than by iterating the event — so a field nobody has classified is
dropped, never sent. tests/lint/telemetry-docs.test.js fails the build if
this table and that catalog disagree.
| Field | What it is |
|---|---|
ts |
ISO timestamp of the event. |
v |
Event schema version. |
mauto_version |
The mauto version that produced the event. |
node |
Node runtime version. |
os |
process.platform — darwin, linux, win32. |
level |
debug, info, warn or error. |
src |
cli or daemon. |
event |
The event name, e.g. verb.end, call.end, daemon.start. |
verb |
The mauto verb, taken from commander's resolved command — never from your command line. |
ok |
Whether the operation succeeded. |
error_kind |
The envelope's error taxonomy: device, timeout, invalid_input, … |
exit_code |
The process exit code. |
dur_ms |
How long it took. |
session_id |
A random id regenerated every time the device daemon starts. Not persisted, not derived from your machine. |
tool |
The mobile-mcp primitive behind the verb, checked against a pinned allowlist. |
call_id |
A monotonic per-call counter minted by the daemon, scoped to one daemon lifetime — pairs call.start and call.end. |
stop_reason |
Why the daemon stopped: idle, signal, shutdown, crash, explicit. |
error_code |
A Node/libuv errno string such as EACCES. |
crash_count |
Integer count of crash reports observed. |
msg_id |
A random per-event id used to deduplicate a re-sent batch. Never reused, so it cannot correlate two events. |
count |
An integer count, e.g. a batch size. |
http_status |
The HTTP status our own telemetry endpoint returned. |
What is never sent¶
These fields exist in your local logs (mobile-automator/.logs/) and are
permanently barred from the network path. tests/lint/telemetry-redaction.test.js
fails the build if any of them is reclassified.
| Field | Why it stays local |
|---|---|
run_id |
Agent-chosen; routinely names an unreleased feature. |
scenario_id |
Names the feature you are testing. |
app_id |
An unreleased product's package name. |
device_id |
A hardware identifier / serial. |
device_model |
Narrows a device to an individual tester. |
project_name |
Your project's name. |
pid |
No aggregate value, and a weak host correlator alongside a timestamp. |
message |
Free text; may embed labels, paths or typed input. |
hint |
Free text; may embed filesystem paths. |
path |
A filesystem path; leaks usernames and project layout. |
How it is delivered¶
Verbs never talk to the network. Every mauto verb ends by exiting, which tears
down a pending socket, so a verb that tried to POST would drop the event a large
fraction of the time and a verb that waited for one would add a network round
trip to every tap.
Instead a verb appends one line to mobile-automator/.logs/telemetry.spool —
that line is the exact payload that would be uploaded, nothing more — and the
device session daemon uploads it during its idle window. mauto telemetry flush
does it on demand. Nothing is retried forever: the spool is capped at 256 KiB,
at most three pending batches are kept, and failed uploads back off from one
minute to thirty.
mauto telemetry flush reports its outcome in two units: sent and dropped
count events (dropped events were permanently rejected by the endpoint
and will not be retried), while kept counts batches left for retry — the
next daemon drain or flush resends them — and kept_events counts the events
inside those batches. The envelope's ok says the verb ran; data.ok is the
flush's own verdict, false when events were dropped or a batch was kept.
Data goes to PostHog's EU cloud (https://eu.i.posthog.com/batch/) using their
plain HTTP capture API and a write-only public project token. No PostHog SDK is
installed; mauto has no analytics dependency.
Reading the queue yourself¶
mauto telemetry status
cat mobile-automator/.logs/telemetry.spool
The spool is plain NDJSON — one upload payload per line. If you disagree with
anything in it, mauto telemetry disable and delete the file.