# 0.4.0

Released 27 October 2026.

Squiggle drives React web apps. Open any react-dom app with `squiggle up --url` and the flows you wrote for your iOS app run on it unchanged, with nothing to install in the app. Studio, your agent's tools, performance and product analytics all work on a browser tab, and the CLI runs on Linux.

## Desktop app

- **New**: Studio lists each browser tab that `squiggle up --url` opens beside your simulators. It mirrors the tab, and you can click, type and scroll in it, pick components and record taps
- **New**: the Devices list has a Web filter while a tab is open
- **New**: Performance has a Web Vitals lane, and LCP, INP and CLS tiles when a session recorded them. The platform filter offers Web
- **Fix**: a device whose app isn't connected says Waiting for app, not another device's app

## CLI

- **New**: `squiggle up --url <address>` opens a React web app in a Chrome, Chromium or Edge window that Squiggle drives, with nothing installed in the app. `squiggle up 5173` works too, and in a project whose app is a web app, a bare `squiggle up` finds its dev server
- **New**: name a web app's address, browser, channel and window size under `web` in `.squiggle/config.jsonc`
- **New**: `--production` drives a production build you serve locally, and `--maps <dir>` reads its source maps when the server keeps them back
- **New**: `--browser` picks the browser by path or command name
- **New**: `squiggle init` sets up a Vite or Next.js app, and `squiggle doctor` says why a web page doesn't connect and how to fix it
- **New**: `squiggle add screen` writes the web version of each template, and a Next.js page for it
- **New**: `squiggle crawl`, `squiggle motion`, `squiggle probe`, `squiggle save` and `squiggle load` work on a browser tab. A save keeps the page, its stores, local and session storage, cookies and IndexedDB
- **New**: `squiggle flows --shards N` runs N flows at a time on a web app, and `squiggle bisect` and `squiggle bakeoff` with `--platform web` serve each commit from its own dev server
- **New**: `squiggle benchmark --suite web` scores your agent on a browser tab
- **New**: `squiggle probe replay --udid web:<origin>` replays a flow in Studio on a browser tab Studio has focused
- **New**: the CLI runs on Linux, x64 and arm64: `npm install -g @squiggle.sh/cli`. A Linux machine is licensed by its machine ID
- **New**: `squiggle bench` starts each run in a series a random 1.5 to 3 s apart, and records the machine's load beside each run
- **Fix**: `squiggle gate relaunch` listens on the port from your config
- **Fix**: `squiggle probe replay --udid` refuses a device Studio isn't focused on, instead of failing to find Studio
- **Fix**: `squiggle up --url` starts Chrome again when it hangs before opening

## Agents & MCP

- **New**: your agent drives a browser tab the same way it drives an app: `target`, `status`, `describe`, `find`, `tap`, `screenshot`, `inspect` and the rest
- **New**: `deterministic_session` turns off a tab's animations and pins its locale
- **Fix**: `probe_read` answers a program whose data is large, instead of waiting until its deadline
- **Fix**: `report_card` runs its flows instead of failing to connect

## Flows & device

- **New**: `emulate: { userAgent }` sets the browser tab's user agent, its `User-Agent` header and the client hints it implies. `emulate` also takes `viewport`, `colorScheme` and `locale`
- **New**: `launchApp: { seed: { cookies, localStorage, sessionStorage } }` opens a web app with cookies and storage already in place, so its first page load reads them. Cookies take the same fields as Playwright's `addCookies`
- **New**: the device commands run on a browser tab: location, orientation, offline, permissions, scripts, screenshots, recordings and file uploads
- **New**: `addMedia` puts a flow's files in the iOS simulator's photo library and On My iPhone, where the photo and document pickers find them
- **New**: selectors take `checked`, `selected` and `expanded`, such as `{ testID: remember, checked: true }`, on a web app
- **New**: a route selector such as `(tabs)/index` matches a web address that never spells the group, so your iOS flows' routes work on the web
- **New**: network stubs, chaos and `--twin` work on a browser tab, including requests a service worker answers from its cache
- **New**: `assert smooth`, the scroll blank-area check and `memoryDelta` measure a browser tab
- **Fix**: a tap on an iOS 26.4 share sheet lands on the control it names
- **Fix**: a hidden match no longer makes a visible one ambiguous
- **Fix**: `squiggle flow --headless` drives the simulator `--udid` names
- **Fix**: a selector with a field Squiggle doesn't know points you to the selectors page on squiggle.sh

## Performance

- **New**: a browser tab records Web Vitals, its frame rate, CPU and heap, network requests with their phases, storage reads and writes, console lines and errors
- **New**: the detectors fire on a web app: slow screens, stalls, memory leaks, request waterfalls, JS-driven animation, render storms and memo misses, each naming your source line
- **New**: a stall on a web app arrives with its CPU profile, named by the hook and line that ran
- **New**: `perf profile`, `perf heap`, `perf crashes` and `perf symbolicate` work on a browser tab, through its source maps
- **Fix**: a symbolicated JS frame names the column the code is at, not the one after it
- **Fix**: a stretch over which the frame rate held steady reports that rate, not "frames unmeasured"

## Product analytics

- **New**: taps and drags on a web page are captured, so recordings, the heatmap and friction findings work on the web
- **New**: the `--platform` filter accepts `web`

## SDK

- **New**: `@squiggle.sh/react` connects your own browser, or any browser, to Squiggle. Add its plugin for Vite (`@squiggle.sh/react/vite`), Next.js (`@squiggle.sh/react/next`), webpack and Rspack (`@squiggle.sh/react/webpack`), or esbuild and Bun (`@squiggle.sh/react/esbuild`). It runs only in development: a production build carries none of it
- **New**: `transport: 'proxy'` connects a page through its dev server, for HTTPS and other machines
- **New**: with a plugin, Zustand stores are named after the variable they are assigned to, and Legend State stores are observed
- **New**: on a web app, `describe`, `find` and `inspect` show the line that renders each element and name each hook, with no Babel plugin
- **New**: Redux and Jotai stores are observed, in React Native and web apps. TanStack Query is observed in web apps
- **New**: routes come from React Router, TanStack Router and Next.js's App and Pages Routers
- **New**: in a React Native development build, call sites, definitions and hook names still show when the Babel plugin's source lines are off
- **New**: the Babel plugin is also at `@squiggle.sh/react-native/babel`, installed with the SDK
- **Fix**: a bare React Native app links Squiggle's native code
- **Fix**: Squiggle's app port refuses requests from web pages, so a page you visit can't pose as your app
