What Graspable sends home, and what it never does
How a desktop app that reads your prompts and your code can report its own errors and count its own use without any of that leaving your computer: the rules we set, where they live in the code, and how to switch it all off.
Michal Takáč 3 min read
Graspable sees a lot. The agent reads your request, opens your files, runs commands in your project and remembers things about how you work. All of that stays on your computer; that was the first decision when we made Graspable a desktop app rather than a website. But an app that stays on your computer is also an app we cannot see break. This post is about what we do send, how it is kept harmless, and where each rule lives, so you can hold us to it.
The one switch
Everything described here follows one setting: Settings → Help improve Graspable. Off means nothing in this post is sent. It is on by default, because the first weeks of a product are when the reports matter most, and because what is sent is designed to be safe to send. The grasp command line shares the same switch (grasp telemetry off) and also honours DO_NOT_TRACK=1.
Ratings are separate. The 👍 and 👎 under an agent's message send something only when you click them, and your request and the message go along only when you tick the box that says so.
Error reports
When something breaks in Graspable's own code, the app sends a short report: the kind of error, its message, where in our code it happened, the version and your system. Before it leaves, a filter takes out anything in the message that could be about you:
- the path of your home folder becomes
~, - email addresses become
<email>, - anything that looks like a key or a token becomes
<secret>, - the message is cut to a few hundred characters.
A failed run is reported too, as its error message alone, through the same filter. The server does the whole thing again before passing the report on, and it keeps nothing about who sent it: no account, no address. A report is not tied to you. The filter and its tests are in one small module we are happy to be judged on.
Counting, not watching
The app counts how it is used: that it was opened, which screen is open, that a project was created and from which template, that a run started and how it ended, that an app was published. The counts carry your account id once you sign in, so we can tell a download from a first project from a plan.
What the app does not do is record what is on the screen. The analytics library we use can capture every click, every typed character and a video of the session. All of that is switched off in the code, and the app's content policy allows no script from the analytics service to load, so it cannot be switched on from outside. A project appears in these counts as a short code made from its id; the code cannot be turned back into a name.
The same goes for grasp and the MCP server. When another agent uses Graspable, we count the command or tool and the name of the client, never the arguments. What the other agent was told by its user is not something we can see, and we do not try.
Why count at all
Three reasons, in order. We need to know whether people get from a download to a working scene, and where they stop. We need to know whether the agent's runs complete, and how often they fail after their repair rounds. And we need to know which of the things we build are used, so the ones that are not can go. None of that needs a prompt or a file; counts are enough.
Where to check
The privacy page lists every event the app and the server send, and is changed whenever the list changes. If you find anything in a report or a count that this post says cannot be there, tell us; it would be a bug, and we would fix it the same day.