hashbrown

What Hashbrown Sends

Hashbrown sends two kinds of usage observations so we can see where developers get stuck: one when a package is installed, and a few while you develop in a browser. Neither includes prompts, messages, schemas, tool arguments, component props, URLs, or thread identifiers.

When you install

Every @hashbrownai/* package runs a postinstall step that sends one package.installed event for that package. The event carries:

FieldWhat it holds
packageName, packageVersionThe package that was installed
osFamily, architectureYour operating system family and CPU architecture
nodeVersionThe Node version that ran the install
packageManager, packageManagerVersionThe package manager and its version, when known
environmentlocal, ci, or unknown
environmentEvidence, ciProviderWhy the environment was classified that way, and the CI provider when there is one
consumerContextWhether the install ran inside a Git checkout
subjectA random per-user id read from or created in ~/.hashbrown/installation-id
installationToken@hashbrownai/core only, outside CI: the random installation id it writes into its package folder

Outside CI, when Git is configured in the installing checkout or globally, the event also carries your Git user.name, your Git user.email, and the owner of the checkout's origin remote when it is hosted on GitHub, GitLab, or Bitbucket. Nothing from Git is sent from CI.

Every package reads or creates the random id in ~/.hashbrown/installation-id (or uses a one-off random id when it cannot write there) and sends it with the event, so repeat installs on one machine are counted once. The step finishes within five seconds and never fails an installation. @hashbrownai/core also writes a random installation id into its own package folder (development-install.mjs and development-install.cjs) and sends it with its event as installationToken, so a development browser can cite the same install.

While you develop

In a development build running in a browser, Hashbrown reports a few milestones, each once per session. A development build is one where process.env.NODE_ENV is not 'production'. Production builds, server rendering, and automated browsers (where navigator.webdriver is set) send nothing. Test runners (Vitest or Jest with jsdom or happy-dom, NODE_ENV=test) send nothing either.

EventWhenFields
runtime.session_startedThe first chat runtime in a session startsPackage name and version, framework, transport kind
runtime.first_stream_completedThe first model stream completesThe same, plus a coarse duration bucket (under 1 s, 1 to 5 s, 5 to 30 s, or 30 s and more)
tool.first_call_executedThe first tool call runsPackage name and version, framework, transport kind
component.first_renderedThe first component the model chose is renderedPackage name and version, framework, transport kind

The framework is react or angular. The transport kind is http, local, delegating, or custom. Every event also carries a random browser id, a session id that rolls over after 30 minutes without activity, and, when the browser can read it from @hashbrownai/core, the random installation id written at install time.

Toolchain

@hashbrownai/core 0.8 reads its installation id through a package imports entry (#development-install), so your bundler and test runner must support package imports. Node 20 and later, Vite, webpack 5, Next.js, the Angular CLI, Jest 29.4 and later, and Vitest all do. Older toolchains, such as webpack 4 or Jest before 29.4, cannot load @hashbrownai/core 0.8.

Turning it off

Stop the install step with either environment variable:

DO_NOT_TRACK=1 npm install
HASHBROWN_TELEMETRY_DISABLED=1 npm install

To see exactly what the install step would send, set HASHBROWN_TELEMETRY_DEBUG=1. It prints the event and sends nothing.

Stop the browser collector for one browser from the developer console:

localStorage.setItem('HASHBROWN_TELEMETRY_DISABLED', '1');

Or for the page, before Hashbrown loads:

window.__HASHBROWN_TELEMETRY_DISABLED__ = true;

Turn it off for the whole app with the provider. A nested HashbrownProvider cannot turn it back on:

import { HashbrownProvider } from '@hashbrownai/react';

export function App() {
  return (
    <HashbrownProvider url="/api/chat" telemetry={false}>
      <Chat />
    </HashbrownProvider>
  );
}

Or turn it off in code before the first runtime is created:

import { setDevelopmentCollectionEnabled } from '@hashbrownai/react';

setDevelopmentCollectionEnabled(false);

getDevelopmentCollectionDiagnostics() returns counters only, so you can check what the collector did without seeing any payload.

Where it goes

Install events go to https://hashbrown.dev/_/growth/collect/v1/install and development events go to https://hashbrown.dev/_/growth/collect/v1/runtime. The data is stored by Hashbrown in a database processed by Vercel (hosting) and Neon (Postgres). It is kept until you ask us to delete it. The privacy page lists every processor for the site as a whole.

Deleting your data

Email brian@hashbrown.dev from the address you want removed. We clear the contact fields tied to it, remove its project mapping, cancel any scheduled email, and redact its observations. A one-way hash of the email address remains so we do not contact you again.

What Hashbrown SendsWhen you installWhile you developToolchainTurning it offWhere it goesDeleting your data