# Probie

> Probie defines success, adds instrumentation, and makes changes in your codebase. Results, customer feedback, and social feeds guide what comes next.

Probie is a developer tool for teams shipping web, Expo, and Swift apps. It captures behavior events from real sessions (never input values), groups the friction into issues, and for GitHub-connected projects opens a pull request with a proposed fix and supporting evidence for a person to review. Anyone can also run a free inspection of a public website. Coding agents can install the SDK from the skill and run inspections over MCP.

## What Probie does

Probie watches real user sessions in your web, Expo, or Swift app and notices the friction people never report: a button clicked five times with nothing happening, a form retried and abandoned, a request that fails quietly. When enough sessions hit the same problem, Probie groups them into one issue with the evidence attached.

For projects connected to a GitHub repository, Probie then reads the codebase, writes the fix with a regression test, and opens a pull request. A person on your team reviews and merges it. After the merge, the behavior baseline for that route flags the friction if it comes back.

Probie also inspects any public website on request. The public form creates a private browser guest identity on first submission; API and MCP callers register email-bound dispatch access first. The inspection runs in a real browser and produces a graded report. Start one at [https://probie.dev/dispatch](https://probie.dev/dispatch), by [HTTP API](https://probie.dev/docs#inspection-api), or over [MCP](https://probie.dev/docs#mcp).

## Install

Sign in at [/get-started](https://probie.dev/get-started) with GitHub, Google, or a magic link, create a project, and copy its widget token from the Integration page. A coding agent can instead register a provisional project after asking its human for an email address and a separate follow-up-consent choice. The token is public by design: it ships to every client that loads the SDK, so it is safe to commit. Projects without a repository are allowed; they get session capture and triage without pull requests.

### Web

Add one script tag before the closing body tag on every page you want watched:

```html
<script src="https://probie.dev/assets/probie-widget.js" data-token="YOUR_WIDGET_TOKEN"></script>
```

This bundle renders a small "Report an issue" button and loads the passive collector. For capture with no visible UI, load the collector on its own:

```html
<script src="https://probie.dev/assets/probie-widget-events.js" data-token="YOUR_WIDGET_TOKEN"></script>
```

Client-rendered apps (React, Next.js, Vue) inject the same tag once on the client; there is no npm package for the web SDK. After load, attribute sessions to a signed-in user with `window.probie('identify', userId)` and to their company or team with `window.probie('group', groupId)`. Pass `null` to either one to clear it, and call `window.probie('reset')` at logout to clear both. The ids are kept in sessionStorage next to the session id, so they last for the browser session and survive a reload.

Optionally, record the outcomes you care about. Automatic capture works without them; with them, Probie can tell which fixes moved a signup or a purchase:

```js
window.probie('group', account.id);
window.probie('track', 'signup_completed', { plan: 'pro' });
```

Event names are 1 to 100 characters of letters, digits, spaces and `_ . : / -`. Props are a flat object with at most 25 keys, and each value is a string (up to 200 characters), a number, a boolean, or null. A numeric `value` prop is read as the outcome value, such as revenue or seats. Probie drops an event that breaks these rules. Track events are sampled with the session, so when `data-sample` is below 1, conversion counts are sampled too. Outcomes that happen on your server, such as a payment, are more reliable sent from there as [server events](https://probie.dev/docs#install-server).

### Expo and React Native

The SDK targets the Expo managed workflow, SDK 50 and later, and has no runtime dependencies.

```bash
npx expo install @probie-dev/react-native
```

```tsx
import { ProbieProvider } from '@probie-dev/react-native';

export default function RootLayout() {
  return (
    <ProbieProvider config={{ token: 'YOUR_WIDGET_TOKEN', apiBase: 'https://probie.dev' }}>
      {/* your app */}
    </ProbieProvider>
  );
}
```

The provider captures JavaScript errors, unhandled promise rejections, network failures, and app lifecycle on its own. Screens, taps, and form friction are opt-in hooks documented in the package README on [npm](https://www.npmjs.com/package/@probie-dev/react-native).

### Swift (macOS and iOS)

The Swift package supports macOS 12 and iOS 15 and later. Instrumentation is explicit; there is no method swizzling.

```swift
.package(url: "https://github.com/ProbieAI/probie-swift", from: "0.1.0")
```

```swift
import Probie

Probie.start(.init(token: "YOUR_WIDGET_TOKEN", apiBase: "https://probie.dev"))
```

Then mark what matters: `.probieScreen("Checkout")` and `.probieTap("buy")` on SwiftUI views, `Probie.form("signup")` for form friction, `Probie.captureError(error)` in catch blocks, and `URLSession(configuration: Probie.instrumented(.default))` for failing requests.

### Server events

Optional. Send outcomes such as signups, purchases and upgrades from your backend, where they actually happen. Send the events your app already records; you do not need to invent new ones.

Server events use a per-project secret key. Generate it in the Server events card on the Integration page. The key starts with `pbs_` and is shown once, because Probie stores only a hash of it. Keep it on your server and never ship it to a browser or app. Rotating the key stops the old one immediately.

```bash
curl -X POST https://probie.dev/api/events \
  -H "Authorization: Bearer $PROBIE_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"events":[{"event":"subscription_started","user_id":"user_123","group_id":"acme","properties":{"plan":"pro","value":49}}]}'
```

From Node 18 or later, the `@probie-dev/node` package batches and retries for you:

```ts
import { Probie } from '@probie-dev/node';

const probie = new Probie({ secretKey: process.env.PROBIE_SECRET_KEY });
probie.track({ event: 'subscription_started', userId: user.id, groupId: org.id, properties: { plan: 'pro', value: 49 } });
await probie.shutdown(); // before the process exits
```

- **`event`**: Required. Same rules as a browser event name.
- **`user_id`, `group_id`**: At least one is required, up to 200 characters each. Use the same ids you pass to `identify` and `group` in the browser.
- **`properties`**: Optional. Same rules as browser props; a numeric `value` is the outcome value.
- **`timestamp`**: Optional. ISO-8601 or epoch milliseconds, from 30 days ago to 5 minutes ahead. Defaults to now.
- **`event_id`**: Optional idempotency key, up to 128 characters. Probie ignores a repeat of the same id within an hour. The Node package always sends one.

A request carries at most 100 events and 256 KB. Probie answers `202` with the number received; `400` with the `index` and `field` of the first bad event, in which case nothing in the batch is stored; `401` for a missing or unknown key; `429` past the per-minute limit; and `503` when it cannot buffer events right now, which is safe to retry.

### Install with a coding agent

The integration skill at [https://probie.dev/skill](https://probie.dev/skill) is a SKILL.md file that walks a coding agent through registration and installation. The agent infers the project name, asks its human for an email and whether limited setup/product follow-up is allowed, provisions a token, installs it, verifies one passive event, and reports the emailed/browser claim flow. Point Claude Code, Cursor, or any agent that reads skills at it, or save it into the repository:

```bash
curl -fsSL https://probie.dev/skill -o .claude/skills/probie-integration/SKILL.md
```

The registration endpoint is `POST /api/agent/registrations`; it requires `email`, boolean `contact_consent`, and a high-entropy `Idempotency-Key` header. Omit `project_name` for inspection access, or include it to provision an integration. Every response includes a dispatch token and signed seven-day claim URL; integration responses also include widget and skill credentials. The MCP tools are split by task: `register_inspection_access` for inspecting only and `register_integration` for installing Probie.

## What the SDKs capture

Every SDK sends the same event types to `POST /api/widget/events` in small, bounded batches:

```text
pageview, click, rage_click, dead_click, scroll_lock, stuck_overlay, stuck_loading, form_submit, form_retry, form_abandon, js_error, fetch_error, page_leave
```

Your code can add named outcome events of its own with `track`, from the [browser](https://probie.dev/docs#install-web) or from your [server](https://probie.dev/docs#install-server). Those carry only the name and properties you send.

The collector is built to see friction without reading content:

- **Input values**: Never read. Form events record that a field was retried or abandoned, not what was typed.
- **Element labels**: Hashed before they leave the page, so a button is recognizable across sessions without its text being stored.
- **URLs**: Query strings are dropped except `utm_*` campaign tags. Fragments are dropped.
- **Cookies**: None set. Sessions are identified by an id generated in the client.
- **Sampling**: Optional per project through the `data-sample` attribute.
- **User and group ids**: Sent only when your code calls `identify` or `group`, or includes them in a server event. Probie stores the id you pass and nothing else about the person, so prefer an internal id over an email address.
- **Event properties**: Sent only with `track` events, and only the properties your code passes.

How the data is stored and for how long is in the [privacy policy](https://probie.dev/privacy). Questions go to hello@probie.dev.

## How a fix is made

When an issue is promoted to a fix, or a ticket is filed from the dashboard or Slack, Probie runs a pipeline of agent roles:

- **Planner**: Reads the evidence and the codebase and writes the plan.
- **Root-causer or architect**: The root-causer traces a bug to its cause; the architect shapes a feature-sized change.
- **Coder**: Makes the change and writes a regression test.
- **Reviewer**: Checks the diff against the acceptance criteria. Failing review sends it back to the coder, up to a configured number of rounds.
- **Rebaser**: Brings the branch up to date with the default branch before the PR is opened.

Each role runs through a configurable agent harness, such as Claude Code, Codex, OpenCode, or Pi, in an isolated container. Commits are authored as Probie Bot on a `probie/*` branch, and the pull request description includes a Tests section that lists the regression tests added.

A person merges. Probie observes the merge or close from GitHub and records the outcome. Probie does not verify individual fixes after merge; what it keeps is a behavior baseline per route, and if the same friction returns on that route the regression is flagged.

## Goals

A goal is the number a project is trying to move, such as paying teams or completed orders, broken into the metrics that drive it. Each metric counts or sums one tracked event. Open Goal in the dashboard sidebar to see the project's goal.

Probie proposes the goal after onboarding, or when you ask from the Goal page. It reads the code and the events the project already sends, then suggests a goal and its metrics. You can edit the objective, target, deadline and directions, remove metrics, or ask Probie to revise it with a note. Nothing is saved until you confirm it.

When a metric needs an event the project does not send yet, the proposal shows where the event belongs in the code and the tracking call to add. For a project with a connected repository, confirming can open a pull request that adds those calls.

After you confirm, Probie records a reading for each metric once a day. A day stays provisional for 30 days, because server events can be backdated that far.

## Website inspection

Anyone can send Probie to a public website. The browser form grants guest access automatically; agents and scripts register dispatch access with an email and consent choice. Probie opens the website in a real Chromium browser, clicks through the pages a first-time visitor would, and writes a report graded A to D with the evidence for each finding.

- Public pages by default. With permission, supported sign-in or account-creation flows can give Probie broader access and produce a richer report.
- Probie reads robots.txt and stays out of what it disallows. Granting permission to sign in is the one exception: to act as a signed-in user Probie may open pages robots.txt asks crawlers to skip. It still avoids payments, publishing controls, and bot checks.
- Reports are public and listed. Each lives at `/report/<id>/<domain-slug>` and appears in the gallery and the sitemap.
- Usage limits apply across the website, API, and MCP. If a limit is reached, Probie tells you when to retry.
- Bot walls stop the inspection. When that happens, the report says the website was protected and explains [how to allow the scanner](https://probie.dev/bot).

### HTTP API

Inspecting only: first register inspection access by omitting `project_name`. Installing Probie: include `project_name` in the same registration request. Keep the returned dispatch token secret.

```bash
curl -s -X POST https://probie.dev/api/agent/registrations \
  -H 'content-type: application/json' \
  -H 'Idempotency-Key: A_RETAINED_RANDOM_VALUE_AT_LEAST_32_CHARS' \
  -d '{"email":"you@example.com","contact_consent":false}'
```

Then start an inspection with the dispatch token as a bearer credential. The endpoint allows cross-origin requests.

```bash
curl -s -X POST https://probie.dev/api/dispatch \
  -H 'content-type: application/json' \
  -H 'Authorization: Bearer YOUR_DISPATCH_TOKEN' \
  -d '{"url": "example.com"}'
```

Add `"signin_permission": true` to let Probie sign in or create an account on the website during that one inspection. Send it only when the person you act for has agreed to it for that website. A signed-in inspection may open pages robots.txt asks crawlers to skip; it still avoids payments, publishing controls, and bot checks. The field must be a real boolean, and it defaults to false.

- **202**: `{"id": 123, "statusUrl": "...", "pageUrl": "..."}`. A new inspection was queued.
- **200**: The same fields plus `"reused": true`. The website already had a live inspection and you were attached to it.
- **400**: `{"error": "..."}`. The body was not JSON, had no `url`, or named a private or reserved address.
- **401**: `{"error": "Unauthorized"}`. The bearer token was missing, invalid, expired, or revoked.
- **429**: `{"error": "...", "retryAfterSecs": n}` with a `Retry-After` header. The hourly limit was reached.

Poll `statusUrl` (`GET /dispatch/{id}/status`) every 5 seconds or so. The payload depends on the state:

- **queued or running**: `{"status", "progress", "queuedAhead", "activity": [...], "chips": {...}}`. `activity` is a short plain-language log.
- **ok**: `{"status": "ok", "reportUrl": "/report/<id>/<slug>"}`. The report is ready.
- **error or skipped**: `{"status", "failureMessage", "allowUrl"}`. `skipped` means a bot wall stopped Probie; `allowUrl` explains how to let it through.

### MCP server

The same surface is available to agents as a remote MCP server at `https://probie.dev/mcp`. It uses Streamable HTTP. Registration and status reads are public; starting an inspection requires the dispatch token returned by registration. Add it to a client:

```json
{
  "mcpServers": {
    "probie": { "type": "http", "url": "https://probie.dev/mcp" }
  }
}
```

```bash
claude mcp add --transport http probie https://probie.dev/mcp
```

- **`register_inspection_access`**: Inspecting only: register an email-bound dispatch identity without creating a project.
- **`register_integration`**: Provision a widget token after collecting the human’s email and consent choice. Requires a retained idempotency key and returns a seven-day claim URL.
- **`inspect_website`**: Start an inspection with a dispatch token. Returns the id and the URLs to poll and open; reuses live and recent inspections.
- **`get_inspection`**: The state of an inspection by id, with absolute report and allow URLs when it has finished.
- **`get_integration_skill`**: The integration skill, with the token filled in when a widget token is passed.
- **`probie://skill`**: The generic integration skill as a text/markdown resource.

Usage limits apply to inspection and registration across both REST and MCP. A rate-limited response tells the caller when to retry.

## Integrations

- **GitHub**: A GitHub App installation gives Probie the repository access it needs to read code and open pull requests. Merge and close events come back through the same App.
- **Sentry**: An inbound webhook turns Sentry issues into Probie tickets, and Sentry evidence is attached to the pull request.
- **Slack**: Notifications when a PR opens, and a `/probie` slash command that files a ticket from a channel.
- **Your MCP servers**: Per project, you can configure MCP servers that the coding agent is given while it works on your repository.

There is no first-party integration with Jira, Linear, Notion, PagerDuty, or Datadog.

## FAQ

### How much does Probie cost?

Website inspection is free and needs no account. The fix pipeline (session capture, triage, and pull requests) is in design-partner access; pricing is agreed per team. [Book a demo](https://probie.dev/pricing) to talk about yours.

### How do I install Probie?

Sign in, create a project, and add the script tag, the Expo package, or the Swift package with your widget token. The [install section](https://probie.dev/docs#install) has the exact snippets, and the [agent skill](https://probie.dev/skill) does it for you.

### Which frameworks and platforms does Probie support?

Any web app that can load a script tag (server-rendered, static, React, Next.js, Vue), Expo and React Native apps on Expo SDK 50 and later, and Swift apps on macOS 12 and iOS 15 and later. Pull requests work for repositories on GitHub.

### What access does Probie need to my repository?

A GitHub App installation on the repositories you choose. The coding agent proposes changes on a `probie/*` branch, commits as Probie Bot, and opens a pull request. Nothing merges without a person approving it.

### What user data does Probie collect?

Behavior events: page views, clicks, rage and dead clicks, stuck loading states, form retries and abandons, JavaScript and fetch errors. Input values are never read, element labels are hashed, query strings are dropped except campaign tags, and no cookies are set. If your code opts in, Probie also stores the user and group ids you pass to `identify` and `group`, and the outcome events and properties you send with `track`. See [what the SDKs capture](https://probie.dev/docs#captured-data) and the [privacy policy](https://probie.dev/privacy).

### What happens after Probie opens a pull request?

Your team reviews it like any other PR. Probie records whether it was merged or closed. Probie does not verify individual fixes after merge; it keeps a behavior baseline per route and flags the route if the same friction returns.

### How is Probie different from Sentry Seer?

Seer starts from an error Sentry already captured. Probie starts from user behavior: rage clicks, dead clicks, abandoned forms, and stuck states that raise no exception. Probie can take Sentry issues as input too. The [comparison page](https://probie.dev/compare/sentry-seer) has the details.

### Can my coding agent use Probie?

Yes. The [integration skill](https://probie.dev/skill) installs the SDK, the [MCP server](https://probie.dev/docs#mcp) at `https://probie.dev/mcp` runs inspections and fetches the skill, and [/llms.txt](https://probie.dev/llms.txt) indexes the documentation in markdown.

### Does Probie work without a repository?

Yes. A project without a connected repository still gets session capture and triaged issues on the dashboard, without pull requests. Website inspection needs no account at all.

### How do I let the Probie scanner through bot protection?

The scanner signs every request with Web Bot Auth (RFC 9421) and publishes its key. Allow verified bots in Cloudflare, or add an exception for the `Signature-Agent` header. [The scanner page](https://probie.dev/bot) has the exact rules.

## Pricing

Website inspection is free. The fix pipeline is in design-partner access while we work with a small number of teams, and pricing is agreed per team.

### Website inspection: free

Send Probie to any public website and get a graded report with the evidence for each finding. No account, no card.

- Public pages by default; supported sign-in or account-creation flows can be enabled for richer coverage. A signed-in inspection may open pages robots.txt asks crawlers to skip.
- Usage limits apply, and Probie tells you when to retry if a limit is reached.
- The report is public and listed, so you can share the link.

Start at [/dispatch](https://probie.dev/dispatch), by [HTTP API](https://probie.dev/docs#inspection-api), or over [MCP](https://probie.dev/docs#mcp).

### The fix pipeline: design-partner access

Design partners get the full product and a direct line to the people building it. It includes:

- Session capture for web, Expo and React Native, and Swift apps, with issues triaged on the dashboard.
- Pull requests with regression tests for projects connected to GitHub, reviewed by a person on your team before anything merges.
- Behavior baselines per route that flag friction when it returns.
- GitHub, Sentry, and Slack integrations, and your own MCP servers for the coding agent.

Pricing is agreed per team based on the projects and volume involved. There are no published tiers yet.

### Questions

Ask at hello@probie.dev. The [FAQ](https://probie.dev/docs#faq-pricing) covers the common ones.

## Comparisons

### Probie and Sentry Seer

Sourced from Sentry's public documentation, September 2026. Corrections: hello@probie.dev.

**Sentry Seer**: Seer is the AI debugging agent inside Sentry. It starts from an error or performance issue that Sentry has already captured, finds the root cause, and can open a pull request with a fix.

- Root-cause analysis for issues Sentry already captured: exceptions, performance problems, and traces.
- Autofix that writes a pull request against a connected GitHub repository.
- Lives inside Sentry, so it uses the stack traces, breadcrumbs, and releases Sentry already has.
- Priced as an add-on to a Sentry plan; Sentry publishes a list price of $20 per month plus usage on its pricing page.

**Probie**:

- Passive session capture on web, Expo, and Swift: rage clicks, dead clicks, stuck loading, form friction, JavaScript and fetch errors.
- Groups sessions that hit the same problem into one issue with the evidence attached.
- Opens a pull request with a regression test for a person on your team to review.
- Keeps a behavior baseline per route and flags the route if the friction returns after the merge.
- Inspects any public website for free, without an account.

**Side by side**:

- **Starting signal**. Sentry Seer: An error, exception, or performance issue Sentry captured. Probie: User behavior: rage clicks, dead clicks, abandoned forms, stuck states. No exception needs to fire. Sentry issues can also be an input.
- **Where it runs**. Sentry Seer: Inside the Sentry product, on the issue page. Probie: A separate dashboard connected to the repositories you choose through a GitHub App.
- **Output**. Sentry Seer: A root-cause analysis and, with Autofix, a pull request. Probie: A pull request with a regression test and a Tests section, reviewed by an acceptance-criteria reviewer before it opens.
- **After the merge**. Sentry Seer: Sentry keeps tracking the issue and its regressions. Probie: A behavior baseline per route flags the friction if it returns. Probie does not verify individual fixes after merge.
- **Platforms**. Sentry Seer: Everything Sentry has an SDK for. Probie: Web via script tag, Expo and React Native, Swift for macOS and iOS.
- **Pricing**. Sentry Seer: Add-on to a Sentry plan; see their pricing page for the current list price. Probie: Website inspection is free. The fix pipeline is in design-partner access, priced per team.

**Pick Sentry Seer when** You already run Sentry, your problems show up as exceptions, and you want fixes proposed on the issue page you already use.

**Pick Probie when** Your losses are silent: users give up on a form or a button and nothing throws. You want the pull request to arrive with the sessions that prove the problem.

Full page: https://probie.dev/compare/sentry-seer

### Probie and Rollbar Resolve

Sourced from Rollbar's public documentation, September 2026. Corrections: hello@probie.dev.

**Rollbar Resolve**: Rollbar is an error monitoring service. Resolve is its AI layer that explains grouped errors and proposes code fixes from the stack traces Rollbar collects.

- Error grouping and alerting across many language SDKs.
- AI explanations and suggested fixes for captured errors.
- Integrations with the issue trackers and chat tools Rollbar already connects to.
- Pricing by event volume; see their pricing page.

**Probie**:

- Passive session capture on web, Expo, and Swift: rage clicks, dead clicks, stuck loading, form friction, JavaScript and fetch errors.
- Groups sessions that hit the same problem into one issue with the evidence attached.
- Opens a pull request with a regression test for a person on your team to review.
- Keeps a behavior baseline per route and flags the route if the friction returns after the merge.
- Inspects any public website for free, without an account.

**Side by side**:

- **Starting signal**. Rollbar Resolve: A captured error with a stack trace. Probie: User behavior in real sessions, with or without an error. Errors are one event type among thirteen.
- **Output**. Rollbar Resolve: An explanation and suggested code, applied by your team. Probie: An opened pull request with a regression test, on a branch in your repository.
- **Repository access**. Rollbar Resolve: Optional, for suggestions that reference code. Probie: A GitHub App installation on the repositories you choose; changes are committed as Probie Bot.
- **Platforms**. Rollbar Resolve: Backend and frontend SDKs for many languages. Probie: Web via script tag, Expo and React Native, Swift for macOS and iOS.
- **Pricing**. Rollbar Resolve: By event volume; see their pricing page. Probie: Website inspection is free. The fix pipeline is in design-partner access, priced per team.

**Pick Rollbar Resolve when** You need broad backend error monitoring across many languages, and you want AI help reading stack traces.

**Pick Probie when** You want the friction users never report turned into pull requests, and you ship web, Expo, or Swift apps.

Full page: https://probie.dev/compare/rollbar-resolve

### Probie and PostHog

Sourced from PostHog's public documentation, September 2026. Corrections: hello@probie.dev.

**PostHog**: PostHog is a product analytics platform with session replay, feature flags, experiments, surveys, and error tracking in one product. It shows you what users do; acting on it is your team's job.

- Event analytics, funnels, and retention with a hosted or self-hosted option.
- Session replay with rage-click and dead-click detection, error tracking, and heatmaps.
- Feature flags, experiments, and surveys.
- A free tier with monthly allowances, then usage-based pricing published on their pricing page.

**Probie**:

- Passive session capture on web, Expo, and Swift: rage clicks, dead clicks, stuck loading, form friction, JavaScript and fetch errors.
- Groups sessions that hit the same problem into one issue with the evidence attached.
- Opens a pull request with a regression test for a person on your team to review.
- Keeps a behavior baseline per route and flags the route if the friction returns after the merge.
- Inspects any public website for free, without an account.

**Side by side**:

- **Purpose**. PostHog: Understand user behavior across the whole product and run experiments on it. Probie: Find the friction that costs users and fix it with a pull request.
- **Friction detection**. PostHog: Rage and dead clicks are surfaced in session replay for you to review. Probie: Rage clicks, dead clicks, stuck loading, and form friction are grouped into issues with a severity, then fixed.
- **Output**. PostHog: Dashboards, replays, and alerts. Probie: Pull requests with regression tests, plus a dashboard of open issues.
- **Data collected**. PostHog: Configurable; replay can record page content with masking options. Probie: Behavior events only. Input values are never read, labels are hashed, no cookies.
- **Pricing**. PostHog: Free tier, then usage-based; see their pricing page. Probie: Website inspection is free. The fix pipeline is in design-partner access, priced per team.

**Pick PostHog when** You want one analytics platform for funnels, replays, flags, and experiments, and your team will act on what it shows.

**Pick Probie when** You want the acting done: the friction found, the fix written, and the pull request waiting for review.

Full page: https://probie.dev/compare/posthog

### Probie and Flowsery

Sourced from Flowsery's public documentation, September 2026. Corrections: hello@probie.dev.

**Flowsery**: Flowsery watches user sessions for frustration signals such as rage clicks and uses AI to explain what went wrong. Details of its fix workflow are in its public materials; this page describes only what those materials state.

- Session monitoring for frustration signals such as rage clicks and dead clicks.
- AI explanations of what users struggled with.
- Pricing on their pricing page.

**Probie**:

- Passive session capture on web, Expo, and Swift: rage clicks, dead clicks, stuck loading, form friction, JavaScript and fetch errors.
- Groups sessions that hit the same problem into one issue with the evidence attached.
- Opens a pull request with a regression test for a person on your team to review.
- Keeps a behavior baseline per route and flags the route if the friction returns after the merge.
- Inspects any public website for free, without an account.

**Side by side**:

- **Starting signal**. Flowsery: Frustration signals in user sessions. Probie: Frustration signals in user sessions, plus JavaScript and fetch errors and form friction.
- **Output**. Flowsery: AI explanations for your team; see their materials for anything beyond that. Probie: A pull request with a regression test, ready for your team to review.
- **Platforms**. Flowsery: Web; see their documentation for the current list. Probie: Web via script tag, Expo and React Native, Swift for macOS and iOS.
- **Free option**. Flowsery: See their pricing page. Probie: Website inspection of any public website is free, without an account.
- **Pricing**. Flowsery: See their pricing page. Probie: The fix pipeline is in design-partner access, priced per team.

**Pick Flowsery when** You want frustration signals explained and your team will write the fixes.

**Pick Probie when** You want the fix written and opened as a pull request, and you also ship Expo or Swift apps.

Full page: https://probie.dev/compare/flowsery

## Guides

### What rage clicks are and how to fix them

A rage click is a burst of clicks on the same element in quick succession. People click like that when they expected something to happen and nothing did, or when it happened too slowly to notice. Rage clicks rarely throw an exception, so an error tracker never hears about them.

#### How many clicks count as a rage click?

There is no standard threshold. Probie counts three or more clicks on the same element, each within about a second of the last, as a rage click. The rule is the same on the web and in Expo and React Native apps, where it applies to taps. A slower cadence usually means a person deliberately trying again, which is a different signal.

Probie records the event as `rage_click` with the click count and the element. Input values are never read and element labels are hashed. The full list of captured events is in the [docs](https://probie.dev/docs#captured-data).

#### What causes rage clicks

Almost every rage click has one of five causes. Each needs a different fix, so the cause matters more than the count.

- **The control does nothing**: The handler was never wired up, the button is behind an invisible overlay, or the click lands on a wrapper element instead of the button.
- **The control works but says nothing**: The request started, but the button shows no pending state, so the person clicks again. On a checkout or signup form that can send the same order or account twice.
- **It only looks clickable**: A card, an icon, a table header, or underlined text looks interactive and is not. Hover styles and a pointer cursor on a plain `div` cause this.
- **The response is slow**: The first click registered, but nothing changed on screen for several seconds.
- **The target moved**: Content loaded above the button and pushed it down between the moment the person aimed and the moment they clicked.

#### Is every rage click a problem?

No. Quantity steppers, carousel arrows, and games invite fast repeated clicks by design. The count alone cannot separate those from a dead button. What separates them is the rest of the session: whether the page changed after the clicks, whether a request failed, and whether the person gave up afterwards.

Probie keeps that context. A session with a rage click is flagged, then a model reads the session trace and decides whether it shows a real problem. Sessions it judges to be noise open no issue.

#### How to find them

Session replay and product analytics tools surface rage clicks for a person to watch. That works when someone has time to review replays. Probie takes the next steps as well:

- The SDK records `rage_click` events from real sessions on web, Expo, and Swift.
- Sessions that hit the same problem are grouped into one issue with the evidence attached.
- For projects connected through the GitHub App, Probie opens a pull request with a regression test. A person on your team reviews and merges it.
- A behavior baseline per route flags the route if the friction returns after the merge.

#### The fix for each cause

- **The control does nothing**: Wire the handler, or remove the element that intercepts the click. The regression test clicks the control and asserts the expected effect: a navigation, a request, or a change on screen.
- **The control works but says nothing**: Disable the control while the request is in flight and show that it is working. The test clicks twice and asserts that only one request was sent.
- **It only looks clickable**: Either make the element do what it suggests or remove the cues: the pointer cursor, the hover state, the underline.
- **The response is slow**: Acknowledge the click at once with a pending state, then make the slow step faster.
- **The target moved**: Reserve space for content that loads late, such as images, banners, and embeds, so the layout does not shift under the pointer.

#### Check your project for the causes

A free Probie inspection finds most of these causes before a real user runs into them. It drives a browser through your public pages and reports controls that do nothing, elements that only look clickable, clicks with no visible response, slow first responses, and layout shifts. It needs no account and no install.

#### Questions

##### What is the difference between a rage click and a dead click?

A dead click is a single click with no effect: no page change, no request, no navigation. A rage click is several clicks in a row on the same element. A dead click often turns into a rage click when the person tries again. Probie records both, as `dead_click` and `rage_click`.

##### Do error trackers catch rage clicks?

An error tracker records exceptions. A click on a button with no handler throws nothing, so it appears only in a tool that records clicks, such as session replay or behavior analytics. Probie records the clicks and can also take Sentry issues as input.

##### What does Probie collect to detect rage clicks?

Behavior events such as clicks, rage and dead clicks, page views, and form submits. Input values are never read, element labels are hashed, query strings are dropped except campaign tags, and no cookies are set.

Full page: https://probie.dev/guides/rage-clicks

### What is there to fix when nothing crashes?

Tools such as Sentry Seer and Rollbar Resolve start from an error that was already captured. The stack trace names the file and line, and an agent can read it and propose a change. That works for failures that raise an exception.

A large share of what drives people away throws nothing. The button does not respond, the save fails without a message, or the form rejects an entry and never says why. The error log stays clean, and the people affected rarely write in to report it.

#### The problems that throw no error

- **Controls that do nothing**: A button with no handler, or one covered by a transparent overlay. The click is swallowed and nothing is logged.
- **Requests that fail without a message**: The API returns an error and the code handles it by doing nothing. The screen still looks saved.
- **Work with no acknowledgment**: A request is in flight and nothing on screen shows it. People click again, and a checkout form can send the order twice.
- **Stuck states**: A spinner that never stops after the network goes idle, a dialog that ignores Escape and outside clicks, or a page whose scroll stays locked after a modal closes.
- **Fields that drop input**: A field that looks editable but discards what is typed into it.
- **Forms people give up on**: A form submitted twice with no error in between, which usually means nothing confirmed the first submit worked. Or a form started and abandoned.
- **People who cannot find their way**: Sessions that bounce between two pages, or click across many elements and never submit anything. These are rarely code defects. They show a page that does not answer the question people came with.

Probie looks for all of these, and none of the checks needs an exception to fire. Most run on behavior events the SDK records in real sessions. Fields that drop input are found by the free inspection, which types into the fields it visits.

#### Why these are harder to fix

An exception comes with its location. A silent failure comes with a sequence of events, and the fix depends on reading that sequence correctly.

- There is no stack trace. The evidence is what the person did: the clicks, the requests, and what happened on screen afterwards.
- Intent matters: three fast clicks are normal on a quantity stepper and a problem on a submit button.
- The fix usually lives in UI code: a missing pending state, an unhandled failure path, an overlay with the wrong stacking order.
- The regression test has to reproduce a behavior, not an exception. It clicks the control and asserts what should happen next.

#### What a fix looks like

- **Double submit**: Disable the submit button while the request is in flight. The test clicks twice and asserts one request.
- **Failed save with no message**: Show the error and keep what the person typed. The test stubs a failing response and asserts the message appears.
- **Dead button**: Wire the handler or fix the overlay. The test clicks the button and asserts the navigation or request.
- **Stuck spinner**: Clear the loading state on every exit path, including errors and timeouts. The test fails the request and asserts the control recovers.

Probie produces fixes like these through the following steps:

- A detector flags a session, and a model reads the session trace to decide whether it shows a real problem.
- Sessions that hit the same problem are grouped into one issue with the evidence attached.
- For projects connected through the GitHub App, a coding agent in an isolated container writes the change and a regression test. A reviewer checks it against acceptance criteria before the pull request opens.
- A person on your team reviews and merges. A behavior baseline per route flags the route if the friction returns.

> Probie does not verify individual fixes after merge. The route baseline is the check that the friction stayed gone.

#### Does this replace error monitoring?

No. Exceptions still need an error tracker, and Seer is a good fit when your problems show up as exceptions. Behavior-based fixing covers the problems an error tracker cannot see. Probie can also take Sentry issues as input, so the two feed the same queue.

#### Check what your project has today

A free Probie inspection drives a browser through your public pages and reports the problems in this guide that it can reproduce without real users: controls that do nothing, fields that drop input, failed requests the screen never mentions, work with no visible acknowledgment, and slow first responses. It needs no account and no install.

#### Questions

##### What is a silent failure?

A failure that produces no exception and no visible message. A request fails and the screen still shows success, or a button does nothing and logs nothing. Only the behavior of the person on the page shows that something went wrong.

##### How is this different from Sentry Seer?

Seer starts from an error Sentry already captured. Probie starts from user behavior: rage clicks, dead clicks, abandoned forms, and stuck states that raise no exception. The [comparison page](https://probie.dev/compare/sentry-seer) has the details.

##### Can every one of these be fixed in code?

Most of them can: dead controls, missing pending states, unhandled failures, and stuck spinners. People bouncing between two pages usually need a product decision instead, such as clearer copy or a different layout. For those, the sessions are the useful part.

Full page: https://probie.dev/guides/fixing-without-errors

## Product and workflow guides

- [AI Code Fixer and AI Debugging for Production Bugs | Probie](https://probie.dev/ai-bug-fixing): An AI code fixer for production bugs. Probie brings error and user behavior evidence into AI debugging, then proposes the change as a GitHub pull request.
- [Production Debugging for JavaScript Errors | Probie](https://probie.dev/production-debugging): Production debugging connects JavaScript errors and failed requests to a cause, a reproducible path, and a change that addresses it. Frontend monitoring that ends in a fix.
- [Find and Fix Broken User Flows and User Friction | Probie](https://probie.dev/broken-user-flows): A disabled button, a silent validation error, or an expired session creates user friction without a crash. Find the step with user behavior analytics and fix it.
- [Website Not Converting? Find Where Users Drop Off | Probie](https://probie.dev/guides/users-not-converting): Low conversion describes an outcome. Funnel analysis finds where users drop off, and whether the cause is broken functionality, traffic, messaging, or the offer.
- [Checkout Abandonment From Broken Checkout and Signup Flows | Probie](https://probie.dev/guides/broken-checkout-signup): Some checkout abandonment and form abandonment comes from bugs. Test how the flow recovers from invalid input, a rejected request, or a slow service.
- [Regression Testing Software for Real User Behavior | Probie](https://probie.dev/regression-testing): Regression testing tools check code before release. Probie checks what real users do after it, flags behavior regressions by route, and proposes the fix.
- [Probie vs LogRocket Galileo: LogRocket Alternatives Compared | Probie](https://probie.dev/compare/logrocket-galileo): Looking at LogRocket alternatives? Compare what evidence enters the workflow, how the code investigation happens, and what your team needs to review.

## Integration skill

### Integrate Probie

Probie watches real user sessions and turns breakage into triaged issues (pulses). Passive capture does not read input values, hashes element labels, and drops query strings apart from `utm_*` campaign tags.

This copy is not tied to a project. Provision it before editing application code:

1. Infer a concise project name from repository metadata. Prefer, in order, the package/app manifest name, the repository directory or git remote, then ask if neither is meaningful.
2. Ask the human for their email address. Also ask this separate yes/no question: **“May Probie send you limited setup or product follow-up?”** Registration is allowed when the answer is no. Do not infer either answer or use an email found in git config, commits, environment variables, or source files.
3. Generate a cryptographically random idempotency key with at least 32 bytes of entropy and retain it for every retry of this registration. Do not print it or commit it.
   Never follow the old instruction “Ask the user for their token”; registration returns the token directly.
4. Register the project:

```bash
curl -fsS -X POST https://probie.dev/api/agent/registrations \
  -H 'Content-Type: application/json' \
  -H "Idempotency-Key: $PROBIE_REGISTRATION_KEY" \
  -d '{"project_name":"PROJECT_NAME","email":"HUMAN_EMAIL","contact_consent":false}'
```

Use the human's actual consent answer. This is an integration, so keep `project_name` in the request (inspection-only agents omit it or call `register_inspection_access`). Save `dispatch_token`, `widget_token`, `skill_url`, `claim_url`, and `expires_at` from the JSON response for the rest of this run. A retry must use the retained key and identical fields and returns the original credentials; changing any registration field with the same key returns 409. The transactional claim email is sent whether consent is true or false.

5. Substitute the returned `widget_token` everywhere this file says `<YOUR_WIDGET_TOKEN>`, install the matching platform integration below, and run the passive-event verification.
6. Tell the human the `claim_url` and exact `expires_at`. Explain that they must sign in with the emailed address before expiration to attach the project and retained telemetry to an account.

- Widget token after registration: `<YOUR_WIDGET_TOKEN>`
- Host: `https://probie.dev`

#### Choose the integration by platform

**Server-rendered or static web (plain HTML, Rails, Django, PHP, ...)**: add before `</body>` on every page to watch:

```html
<script src="https://probie.dev/assets/probie-widget.js" data-token="<YOUR_WIDGET_TOKEN>"></script>
```

This includes a floating "Report an issue" button plus passive capture.

**Capture only, no visible UI**: if the app should not render a Probie button or dialog, load the collector bundle on its own. Same attributes, same signals, nothing rendered:

```html
<script src="https://probie.dev/assets/probie-widget-events.js" data-token="<YOUR_WIDGET_TOKEN>"></script>
```

Use this when the product has its own feedback surface, or when the UI is not wanted on the page. The reverse (`data-events="0"` on the main widget) gives button-only with no capture.

**React / Next.js / Vue via npm (client-rendered)**: no package to install; the script is served from the Probie instance. Inject once on the client, env-gated so dev and preview builds no-op:

```js
// Root layout / app entry. Guard for SSR: the widget needs the DOM.
const token = process.env.NEXT_PUBLIC_PROBIE_TOKEN; // set to <YOUR_WIDGET_TOKEN> in the deploy env
if (token && typeof document !== 'undefined' && !document.getElementById('probie-widget')) {
  const s = document.createElement('script');
  s.id = 'probie-widget';
  s.src = 'https://probie.dev/assets/probie-widget.js';
  s.dataset.token = token;
  s.async = true;
  document.body.appendChild(s);
}
```

For capture only with no visible UI, point `s.src` at `https://probie.dev/assets/probie-widget-events.js` instead. Everything else stays the same.

After load, attribute sessions to a signed-in user: `window.probie('identify', userId)`. This works with either bundle. If the app has companies, teams or workspaces, also call `window.probie('group', groupId)` where the user's current one is known. Pass `null` to clear either, and call `window.probie('reset')` at logout next to the app's other analytics resets.

**Expo / React Native (native)**

This is a two-step install. **Do step 1, then stop.** Step 2 is optional and must not be done unless the user asks for it.

*Step 1, the whole install:*

```bash
npx expo install @probie-dev/react-native
```

The package has no runtime dependencies and cannot conflict with the app's Expo SDK. **If npm reports a version conflict, do not "fix" it.** Never add an `overrides` or `resolutions` block to the app's package.json, never pass `--legacy-peer-deps` or `--force`, and never change the versions of the app's existing packages. Stop and report the conflict: it is coming from something other than this package.

Then mount the provider once at the app root. Find the real root rather than assuming: Expo Router apps use `app/_layout.tsx`, classic apps use `App.tsx`. Add the token directly: it is public and belongs in source the same way a Sentry DSN or PostHog key does:

```tsx
import { ProbieProvider } from '@probie-dev/react-native';

export default function RootLayout() {
  return (
    <ProbieProvider config={{ token: '<YOUR_WIDGET_TOKEN>', apiBase: 'https://probie.dev' }}>
      {/* the app's existing root content, unchanged */}
    </ProbieProvider>
  );
}
```

That is the install. It captures JS errors, unhandled promise rejections, network failures, and app lifecycle. Do not add env-var plumbing, wrapper components, identify/reset call sites, or navigation and tap instrumentation as part of this step. Stop here and tell the user what step 2 would add.

*Step 2, richer capture, only when asked:*

- Screens: `useProbieExpoRouter()` (Expo Router) or `trackScreen(name)` (hand-rolled navigation)
- Taps and rage-taps: swap `Pressable` for `ProbiePressable` on the elements that matter
- Form friction: `useProbieForm()`: telemetry only, it does not perform the submit
- User attribution: `identify(userId)` at login, `reset()` at logout

Exact signatures are in the package README (`node_modules/@probie-dev/react-native/README.md`) and its TypeScript types. Add one signal at a time; each is independent.

Expo on web: use the npm/web path above when `Platform.OS === 'web'`.

**macOS / iOS (Swift, native)**: add the SwiftPM dependency and start the SDK once, early. Instrumentation is explicit: there is no auto-capture or swizzling:

```swift
// Package.swift dependency (Xcode: File → Add Package Dependencies… with the same URL)
.package(url: "https://github.com/ProbieAI/probie-swift", from: "0.1.0")
```

```swift
import Probie

// App init. Read the token from build config (xcconfig/Info.plist) and skip
// start() when it is absent so dev builds capture nothing.
if let token = Bundle.main.object(forInfoDictionaryKey: "ProbieToken") as? String, !token.isEmpty {
    Probie.start(.init(token: token, apiBase: "https://probie.dev"))
}
```

Then instrument where it matters: `.probieScreen("Checkout")` / `.probieTap("buy", label: "Buy now")` on SwiftUI views, `Probie.form("signup")` for form friction, `Probie.captureError(error)` in catch blocks, and `URLSession(configuration: Probie.instrumented(.default))` for failing-request capture. `Probie.identify(userId)` at login, `Probie.reset()` at logout; both are safe no-ops if start() never ran. Sandboxed macOS apps need the `com.apple.security.network.client` entitlement.

**Optional: outcome events.** Skip this unless the app already records outcomes for another analytics tool. Automatic capture is the complete install; outcome events only add a stronger signal of what a fix changed. Where the codebase already sends a signup, purchase, upgrade or similar to PostHog, Segment, Mixpanel or its own analytics, mirror that call next to it with the same event name:

- In the browser: `window.probie('track', 'signup_completed', { plan: 'pro' })`. Props are flat (string, number, boolean or null, at most 25); a numeric `value` prop is the outcome value.
- On the server, when the outcome happens there (payments, webhooks): `@probie-dev/node` with the project's secret key, read from an env var such as `PROBIE_SECRET_KEY`. The human generates the key on the Integration page; never put it in client code or commit it. See https://probie.dev/docs#install-server.

Don't invent events the app doesn't already track, and don't add tracking to flows that have none.

#### Conventions

- Mirror the codebase's existing analytics wiring (PostHog, Segment, ...): same file layout, same env-gating pattern, identify/reset at the same call sites.
- The token is public and safe to commit. Env-gating is optional: do it only if the team already gates its other analytics, or if they ask to keep local development out of pulses. On native, read the env var into a variable and render the plain children when it is missing (`ProbieProvider` throws on an empty token); on web, skip injecting the script.
- Do not double-install: check for an existing Probie script tag or provider first.
- Change as little as possible. Adding Probie should touch one file on native and one on web. If a change requires editing a lockfile, a build config, or another package's version, stop and ask first.

#### Verify before claiming done

1. Web: render the app with the env var set and confirm the HTML contains exactly one Probie script tag with `data-token`; without the env var, zero. Native: confirm the app still builds and that `git diff` touches only the root layout and, for a fresh install, package.json's dependency on `@probie-dev/react-native`.
2. Prove the pipe end-to-end (uses the real token; sends one synthetic pageview):

```bash
curl -s -X POST https://probie.dev/api/widget/events -H 'Content-Type: application/json' -d '{"token":"<YOUR_WIDGET_TOKEN>","events":[{"type":"pageview","ts":'$(date +%s000)',"session_id":"skill-verify","url":"","route":"verify","referrer":"","element":null,"payload":{}}]}'
```

Expect `{"received":1,...}`. A 401 means the token is wrong; a 400 names the malformed field.

3. Do not submit a Pulse or expect derived analytics before the human claims the project. A successful synthetic passive event is the complete pre-claim verification. Report the saved claim URL and expiration now.


