Why Squiggle

Your React Native app, tested, profiled and driven from the inside.

Squiggle runs inside your app and lets your tools see what it is actually doing: every component, route, request, tap and frame. Tests stop breaking on redesigns, slowdowns point at the line that caused them, and your AI agent can use the app like a teammate instead of guessing from screenshots.

The browser demo is the real Studio, driving a live demo app. Nothing to install.

6steps
squiggle init does most of them and shows each change first.
to a first flow
5s
Kept before every crash, error or stall, ready to replay.
of rewind
0turns
Once an agent solves a step, later runs need no model.
agentic flow, replayed
≤185ms
For an agent to tap and see what changed on screen.
agent tap

01 — The idea

One model of your app, instead of a tool per job

Most tools look at your app from the outside: pixels, coordinates, sampled stacks, hand-written events. Squiggle runs inside it and keeps one live model of what it is doing. Tests, performance, analytics and agents all read that same model, so they agree with each other and with the code.
  • UsuallyUI tests that tap coordinates and break on every redesign

    With SquiggleFlows that name what a control is, and repair themselves when it moves

  • UsuallyA profiler that hands you samples and leaves the detective work to you

    With SquiggleFindings that name the component, the request or the line

  • UsuallyAn analytics SDK you tag by hand, screen by screen

    With SquiggleScreens, taps and funnels the app was already reporting

  • UsuallyAn AI agent squinting at screenshots and guessing coordinates

    With SquiggleAn agent that reads the app itself and acts by name

02 — Testing

Tests that survive a redesign

A Squiggle flow names a control by what it is, not where it sits. Try it: ship a redesign to this screen, then rename the button's testID, and watch which tests keep passing.

The screen your tests were written against.

  1. Coordinatestap(110, 244)Passed: pressed “Sign in”
  2. Text selectortap(text('Sign in'))Passed: pressed “Sign in”
  3. Squiggle flow- tap: { testID: sign-in }Passed: pressed “Sign in”
flows/login.yaml
flow: log inenv:  USER: guest@acme.comsteps:  - type: { into: { testID: email-input }, value: '${USER}' }  - type: { into: { testID: password-input }, value: hunter2 }  - tap: { testID: sign-in, label: submit credentials }  - waitFor: { route: checklist, timeout: 8000 }  - assert:      visible: { text: '${USER}' }

Plain YAML that reads like the journey. waitFor watches the app, so there are no sleeps to tune.

  • A pass means it happened. Assertions look at the app again, because a tap that was sent is not the same as a tap that worked.
  • Failures explain themselves. The report names the step, what it looked for, what was there instead, and what to try next.
  • Repairs are reviewable. A healed selector is rewritten in the flow file, so the fix arrives as a diff, and the run says how many heals it took to pass.

03 — AI agents

Your coding agent can finally use your app

Connect Claude Code, Copilot or Codex with one command. Instead of a screenshot-and-guess loop, the agent writes the whole journey as one program. Squiggle runs it and asks the model again only when something needs a decision. Watch where the model turns go:

TaskSign in and check the balance

  1. A typical agent loop

    Screenshot, think, act, one action at a time.

    5model turns

  2. Squiggle, first run

    One program for the whole journey. The model is woken again only for a decision, like a popup.

    1model turn

  3. Squiggle, every run after

    The verified steps were saved beside the flow, so they replay with no model at all.

    0model turns

  • Reads the app, not pixels

    The agent sees the component tree, the route and the state, and taps controls by name. Each action returns what it changed, so the next step needs no extra look.

  • Destructive taps need you

    Squiggle refuses risky actions below the model, not in a prompt. You approve each one explicitly, once, and it is logged. Your flow secrets never reach the model.

  • Claims you can check

    Everything the agent reports points at the session and event it came from, so you can verify a claim instead of trusting a summary.

04 — Performance

Slowdowns that point at the line

Squiggle records performance all the time, with no profiling session to start. Detectors read it and report what they find in plain words, with the source line, the evidence, and a fix your agent can make. Pick one:

warnrender-storm

PriceTicker rendered 48× in one interaction

Where
src/screens/Markets.tsx:41
Evidence
48 commits after one tap on Markets, each linked to its render row

propose_fix → your coding agent

PriceTicker reads the whole prices store, so every tick renders it. Select only the price it shows, then re-run the flow to confirm the finding is gone.

  • Live in Studio. Findings appear while you use the app, each announced once, not buried in a report you have to remember to open.
  • Gate it in CI. Snapshot a baseline, diff a branch against it, and fail the pull request when a number moves the wrong way.
  • All the way down. Flamegraphs, heap diffs, a network waterfall and symbolicated native crashes, from the same recorded session.
Terminal
squiggle perf snapshot --label main# … change something, run the flow again …squiggle perf diff --against main --assert thresholds.json   # fails CI on a regression

05 — Studio

See inside your app while it runs

Studio is the Mac app around all of this. Every card below opens it right here in your browser, on a live demo app, with a short guided tour.

06 — Getting started

From install to your first flow

Works with Expo and bare React Native apps in the iOS simulator, and with React Native macOS apps. squiggle init does most of the setup; the rest is one wrapper and a rebuild.
  1. npm install -g @squiggle.sh/cli

    Or install the Mac app, which includes it.

  2. squiggle activate --trial

    14 days, every feature, no card.

  3. squiggle init --agent claude

    Sets up your app and shows each change first. Or copilot, or codex.

  4. <Squiggle navigationRef={…}>you edit

    Wrap your root so screens are tracked. init prints the code.

  5. npx expo run:ios && squiggle up

    Rebuild once, then launch with Squiggle attached.

  6. squiggle doctor

    Names anything still missing, with the fix.

Public beta · 0.2

Try it on your own app

The CLI is on npm and the Mac app is signed and notarised. The trial is 14 days, with every feature and no card.