Reports

Seven local AI tools, and which ones phone home

The Local AI Telemetry Report 2026 tests them on one Mac: what they send and which off switches work. Free PDF and dataset.

0:00
Seven local AI tools, and which ones phone home
Illustration: StrideNote
Seven local AI tools, and which ones phone home

Download the report

Enter your email and the PDF opens straight away. The address stays with us and goes to no third party.

A model that runs on your own laptop cannot send your prompts anywhere. The software wrapped around it can, and two of the seven tools we tested did, before anyone had typed a word.

The Local AI Telemetry Report 2026 is the first report from Stridenalysis, the research desk of StrideNote. It gathers eleven investigations we published between June and August 2026 into one question: what does a local AI tool send from the machine it runs on? Seven tools from a working local AI stack went through the same inspection on one test machine, an Apple M4 Pro with 48 GB of memory. We read their code, listed every network connection they held and, where we could, captured what they sent. Every finding carries an evidence grade, and the dataset behind every chart is published with the report.

The PDF is free. Enter your email in the download box and it opens straight away.

What did the local AI telemetry report find?

Four of the 13 findings in the dataset show data sent to a reporting service without the user asking. None of our captures showed a prompt or a file leaving the machine. In every capture we made, the payload held counters, timings and hashed names. Where we did not capture a payload, as with OpenCode, the finding stays open.

OpenJarvis, the personal agent framework from Stanford, ships with analytics switched on. During use it sends one event per chat session to a PostHog host, with turn counts, token counts, latency figures, a hashed model name and an anonymous install ID, and flushes it on a 30 second cycle. We redirected that host to a listener on our own machine and captured the one request byte for byte. It held no message content. The switch that turns it off, enabled = false under an [analytics] heading in the config file, works. The project’s documentation promises to explain how to opt out and never names it. The full test is in our OpenJarvis retest, which also covers the background model downloads nobody asked for and the port conflict that made the desktop app look broken. The first A/B capture of both agents is in OpenCode vs OpenJarvis: which local AI agent phones home?

Update, 19 October 2026: OpenJarvis has since merged a change, on 14 October, that makes its analytics opt-in. We tested desktop-v1.0.2 in July, when analytics was on by default, and as of today that is still the newest desktop release on the project’s GitHub page. We have not retested the new code, so this section describes the version we tested.

OpenCode, the desktop coding agent, opens two outbound connections at launch, one of them to its Sentry crash-reporting endpoint, before any input and with no project open. The production address is compiled into the app, and the Breadcrumbs integration has been deliberately stripped. Sentry’s own list of what its SDK collects runs to stack traces, OS and runtime versions, and the IP address of the request. OpenCode ships 41 OPENCODE_DISABLE_* flags, and none of them controls that connection. We did not capture a payload, and the report says so in the same sentence as the claim. The socket listing and the bundle reading are in the OpenCode desktop section of the Local Agent Telemetry Report 2026 page.

The data trail that matters is often ordinary. LM Studio holds no telemetry settings and opened no outbound connection at rest: six processes, three sockets, all on localhost. On a default install it routes every model search and download through its own proxy, which then sees what you look for and the address doing the looking. The Hugging Face library that sits under most model downloads carries a 125-line telemetry module that nothing in the library calls, and adds your Python and PyTorch versions to a header on every request instead. Hugging Face documents an HF_HUB_DISABLE_TELEMETRY variable; it governs the function nothing calls, not the header. Both behaviours are disclosed, and both create a record of what you are building.

Alarming names made poor evidence. Fifteen hits for “amplitude” in OpenCode were an SVG filter attribute. More than 150 references to OpenTelemetry had no exporter and no collector address. Graphify, the tool we trusted least, opened no connection beyond the local model server in 358 socket samples. Before installing it we read the whole of Graphify’s source: zero hits for telemetry, tracking or usage statistics, and eight hard-coded addresses, six of them model providers you would have to choose. The socket test found LM Studio every time. Section 5 of the report lists all six false leads, because a method that cannot catch them is not a method.

The report also carries one case reported by others. In How AI companies hide tracking code we covered Claude Code, where a check on the user’s server and timezone was encoded into the date line of every prompt. A reader of the code found it in a public issue filed on 10 June 2026, and an engineer on the Claude Code team acknowledged it on 30 June.

Crash reporters: shipped in three apps, wired to nothing

Open Activity Monitor while a local AI app is running and you will find a process called chrome_crashpad_handler underneath it. LM Studio, OpenCode and Visual Studio Code are all Electron applications, so each embeds a copy of Chromium, and Crashpad is Chromium’s crash-reporting system. Searching each bundle finds exactly one crashpad binary in all three. Its presence tells you the app is built on Electron. It tells you nothing about whether crash data leaves the machine.

Electron’s crashReporter API sends a report only when the application calls crashReporter.start() with a submitURL pointing at a collector. Without a destination, crashpad still catches crashes and writes dumps locally, with nowhere to send them. The strings submitURL and uploadToServer appear in all three bundles, because the framework code that reads those parameters is bundled too. No bundle assigns an actual URL to them. The live check agrees: LM Studio’s crashpad handler was running throughout our inspection and held no sockets at all, not even a listener.

Counting references to crashReporter gives LM Studio one, OpenCode two and Visual Studio Code thirty-six. Microsoft ships far more crash-handling code than either AI tool, and still has no collector address in the bundle we inspected. The volume of code is not the signal. The destination is.

Bar chart showing three Electron-based AI apps each ship one crashpad binary, with zero configured upload URLs between them.
Three apps, three crash handlers, no configured destination among them.

OpenCode’s error reporting travels through the Sentry JavaScript SDK, an ordinary dependency with no distinctively named process for anyone to notice. LM Studio carries no Sentry references at all. The component with the alarming name is idle, and the component doing the reporting is a library nobody would look at twice. We did not induce a crash in any of the three, so we cannot rule out a later route for the local dumps. For a tool where reporting did reach outside, see ArtCraft telemetry, where the app loads two trackers before sign-in.

Machine identifiers written to disk

An IP address changes when you move and is shared across a household. A persistent identifier written to disk survives reboots and network changes, and it turns a scatter of anonymous requests into one continuous profile of a single machine. We swept five tools for identifier-shaped values in everything each one writes to disk. A pattern search said four of the five carry one. Reading what those values are brought it down to two.

Visual Studio Code carries three. Its storage.json holds twelve keys, and three of them are identifiers: telemetry.machineId, telemetry.sqmId and telemetry.devDeviceId. Microsoft documents them in its telemetry documentation. OpenCode carries one, a file named .updaterId in its application support directory holding a 36-character hexadecimal value. It was created the day the app was first run and has not changed since. Its stated purpose is the update mechanism. OpenCode is also the tool we saw contact a crash-reporting endpoint at launch, so it is the one install where a persistent identifier and an outbound connection both exist. OpenJarvis keys each analytics event to an anonymous install ID, which our capture confirmed.

Bar chart comparing identifier-shaped matches per tool against genuine persistent identifiers, five tools surveyed.
What a pattern search finds, against what survives being read.

The false positives each had a different cause. LM Studio returned thirteen matches, every one inside liblmstudio_bindings.node, a compiled binary, repeated across four bundled llama.cpp backend versions; its settings file holds no identifier key. Pi returned twenty matches, all session log filenames, with twenty-one distinct UUIDs across those files, one per conversation. The Hugging Face cache returned nothing. We have not captured outbound traffic from Visual Studio Code or OpenCode to see whether either identifier leaves the machine.

How did we test seven tools on one Mac?

Every tool sits on the highest step of an evidence ladder we could reach for it. Grade A is a capture: we pointed the tool’s reporting host at a listener on the same machine, ran one fixed task with the setting on and then off, and recorded every request. Only OpenJarvis reached that step. Grade B is sockets: every network connection held by every process of the running tool, with the addresses resolved. Anything bound to 127.0.0.1 is talking to the machine it runs on; an established connection to an outside address is a question, and we resolve the address to see whose it is. OpenCode, LM Studio and Graphify sit there. Grade C is code: what the shipped bundle, the settings and the files on disk say the software is built to do. The Hugging Face library, Visual Studio Code and Pi rest on that step.

Two rules held throughout. A search count is not a finding; a string in a bundle shows that a byte sequence is present, and only the code around it shows what it does. Presence is not transmission; a crash reporter or an analytics library is a finding once there is an address it reports to, and the strongest evidence is a connection to that address. Every retest that changed a finding is recorded in the article it changed.

The limits are stated in the report rather than left for a reader to discover. Every test ran on one Mac, on the version installed at the time. Socket listings are snapshots, so a tool that reports every few hours would not appear in one. We induced no crashes. The identifier sweep inspected files at a fixed depth and skipped caches and model directories. Two tools, Visual Studio Code and Pi, were not network-tested at all and appear only in the disk and bundle checks. Our method guide, how to prove your data never leaves, explains why we grade evidence this way.

How can a business use the findings to approve a local AI tool?

Each finding maps to a choice an IT or security team can make on the day it approves a tool. These are conditions, not quality verdicts: the settings under which each tool behaved the way our captures and socket listings showed.

OpenJarvis can be approved with a configuration line. Setting enabled = false under [analytics] stopped the one usage event per session in our capture. Ship that line with the install, and redirect the installer’s own analytics call, which has no off switch.

OpenCode cannot be quietened from inside the app. Its crash reporter connects at launch, and none of its 41 disable flags reaches it. The choices are to accept that connection or block the Sentry host at the network. We have not captured that payload, so a cautious team treats the finding as open.

LM Studio opened nothing outbound at rest, but model search goes through its own proxy by default, so its operator sees which models staff look for. Decide whether those search terms matter to you. For the Hugging Face library, expect Python and PyTorch versions in a header on every download request; the documented telemetry variable does not change that. Graphify, pointed at a local model server, stayed on the machine across 358 socket samples. Approve the exact package name and the local backend together.

Do not block an Electron tool on the crashpad process name alone. The three apps here ship one crashpad binary each, and one of them is Visual Studio Code, so a review that blocks on the binary blocks that too. A short review sheet for an Electron AI tool:

  • Is crashReporter.start() called, and is a real address assigned to submitURL?
  • Is there another reporting channel, such as a Sentry DSN or an analytics host? In OpenCode’s case the reporting went through the Sentry JavaScript SDK, not through crashpad.
  • Which outbound connections does the app hold at rest, recorded on a clean user account and kept with the approval?
  • Where are crash dumps written on disk, and who can read them? Crashpad writes them locally whether or not it uploads them, and a dump can hold file paths.

A tool with no destination in the first two answers and no unexplained connection in the third has passed these checks, with a note on local dumps still owed. A tool that fails any of them needs the vendor’s written answer on what is sent and how long it is kept.

Machine identifiers can matter for data protection. The UK GDPR definition, as the Information Commissioner’s Office sets it out on its what is personal data page (read on 17 October 2026), lists “an online identifier” among the identifiers that can make a person identifiable. A value written once per installation on a staff member’s laptop is the kind of thing that wording covers. Whether a particular ID is personal data in your setting is a judgement for your data protection lead, and this is not legal advice. On the five tools we swept, that gives a team two to raise, Visual Studio Code and OpenCode, and three where the sweep found nothing to record.

For a procurement file, the report is the document to attach: it gathers these findings into one dataset with an evidence grade on each, and it records the version tested every time.

How do you check your own AI tools for telemetry?

Four of the five checks need nothing beyond what ships with the operating system. Open the tool and do nothing, then list the connections its processes hold; on macOS, lsof -nP -iTCP -a -p PID does this for one process, and an established connection to an outside address is a question worth answering. Read the settings file for keys named for analytics, telemetry or usage, and for proxy or mirror settings, and check whether an access token is stored, because a token turns an anonymous request into an attributed one. Look for the destination rather than the machinery: a DSN, a collector URL or a hard-coded host, because a library with no address sends nothing by that route.

Filter identifier-shaped values by where they live. A value inside a compiled binary is a build constant. Many values that grow with use are session IDs. One value in a small file or a settings key, created at install and unchanged since, is a machine identifier. Electron applications keep this kind of state in a predictable place under application support, and the app API is where that path is defined. A further filter helps on a tool we did not cover: check the file’s creation date against the day you installed the app. A machine ID is written once, at first run; a value that keeps changing its modification time is doing some other job, and one created long after install was probably generated in response to something.

The fifth check is the capture, and it is the only one that shows the bytes. When a tool lets you set its reporting host, point it at a listener on your own machine and run the same task with the setting on and off. Where a tool does not expose that setting, as OpenCode does not, the honest result is an open finding, not a clean one.

Section 7 of the report walks through each of these with the exact keys and paths we used, and the case studies show what a positive result looks like.

Where can you download the report and the dataset?

The PDF runs to 30 pages. Inside:

  • A summary of the six findings, and the four numbers behind them
  • The method and the evidence ladder, from code reading to byte-for-byte capture
  • Results by tool, with 18 figures: OpenJarvis, OpenCode, LM Studio, huggingface_hub, Graphify, Visual Studio Code and Pi
  • Six leads that looked like telemetry and were not
  • A case study on Claude Code, reported by others
  • Five checks anyone can run, the limitations, and the tests planned for the next edition
  • Three appendices: the dataset, the sources and a glossary

The dataset, local-ai-telemetry-2026.csv, has one row per finding: tool, version, test date, evidence grade, method, destination, trigger, what is sent, whether it is on by default, and what we found of an off switch. Every row links to the published investigation it came from.

The report and its dataset are licensed CC BY 4.0. Copy them, share them and build on them, with credit to StrideNote. The permanent record is on Zenodo under DOI 10.5281/zenodo.22848632. To cite it: StrideNote (2026) Local AI Telemetry Report 2026. Edited by StrideNote Studio. Stridenalysis Reports, edition 1. No company named in the report paid for it or reviewed it before publication. If you find an error, write to us at the address on our About page and the correction will appear in the next edition.

What will the next edition test?

Edition 1 rests on the evidence we had. Its biggest gap is the OpenCode payload: the findings there rest on connections seen, not content captured, so the first test on the list is an error capture with a local sink in place. LM Studio gets a full working day of recorded requests instead of a snapshot. Hermes Agent, the always-on assistant in our own stack, has not yet been inspected. Pi and Visual Studio Code move from disk checks to socket evidence, and Ollama, the runtime the OpenJarvis installer added, joins the list. Two tests carried over from the crash reporter and identifier work are also on it: inducing a crash in LM Studio, OpenCode and Visual Studio Code to watch for any upload of the local dumps, and capturing traffic from Visual Studio Code and OpenCode to see whether their identifiers leave the machine.

The next report narrows to agents. The Local Agent Telemetry Report 2026, published on 26 September 2026, covers sixteen coding and task agents with the same evidence ladder and a version recorded for every test. A tool that is absent from either report has not been cleared by us. It has simply not been tested yet.

More from Reports