Changelog

0.3.0

Released 24 October 2026.

Desktop app

  • Newsave the app's current screen and data from the device panel's Capture menu, and load it back in under a second
  • Newa Tunings screen shows what squiggle flow --tune and --repair measured and what they propose
  • NewPerformance has a Probes section: write a rule, install it on the connected app, and see when it held
  • NewProduct has a State section, showing what your app held on each screen
  • NewAnalytics names the control each touch landed on, and what each drag was meant to do
  • Newthe tour has 25 chapters, folds its sections and shows how much you've read. Every chapter has a hint
  • Newmenu items show their keyboard shortcut, such as Show all devices (⌘G)
  • NewSettings are grouped into sections, and the simulator stays in view while you change them
  • Newa healed step shows how close the match was, and warns when it was close to failing
  • FixStudio checks for updates on every launch, and Check for Updates opens the update card
  • FixStudio's Replay goes to the flow's start screen first, as squiggle flow does
  • Fixzooming into a live timeline no longer jumps when the session grows, and a timeline parked at the end follows it
  • Fixhover cards on graphs stay above everything and inside the window, and close with the session they describe
  • Fixthe inspector's selection box stays inside the device screen and follows a scroll
  • Fixthe Renders table keeps the Component column in view while it scrolls sideways
  • Fixa popover over the device preview scrolls instead of the device
  • FixStudio no longer reloads an app that another tool is driving
  • FixStudio removes a recent project whose folder is gone
  • PerfStudio's JS thread idles with an app connected: live performance analysis reads only what changed

CLI

  • BreakingSquiggle saves an app's runs, recordings and performance data only into the project that owns it: the app is listed under apps in .squiggle/config.jsonc, or its development build was built inside the project. Any other app still works live, but nothing about it is saved. If an app's data stops appearing, add it to apps
  • Breakingwith more than one simulator booted, a command that drives a device refuses to pick one and lists them (E_DEVICE_AMBIGUOUS). Name one with --udid, SQUIGGLE_UDID or udid in your config. Your agent's tools refuse the same way
  • Newsquiggle card checks whether a change is done: it runs the flows that reach the screens you changed, checks what they measured, and lists each problem with the line to fix
  • Newsquiggle add screen writes a new screen from one of six templates, with a flow that drives it and a renders budget it meets
  • Newsquiggle save and squiggle load keep the screen the app is on, with the data behind it, and put it back in under a second instead of tapping through screens
  • Newsquiggle bisect finds the commit that slowed a flow, without rebuilding the app. --hunks says how much of the slowdown each change in that commit accounts for
  • Newsquiggle bakeoff runs one flow against several revisions and compares pass rate, duration, renders, dropped frames, memory growth and startup in one table
  • Newsquiggle motion records how a view moves after a tap and gives you the withSpring config that reproduces it
  • Newsquiggle contracts propose turns what your passing runs always showed into asserts in your flows, and proposes removing an assert that stopped holding
  • Newsquiggle perf budget checks each screen's budget against the newest session, with the margin to each limit. --changed checks only the screens your branch changed
  • Newsquiggle perf labels exports every run with its outcome, heals and app state, as JSONL
  • Newsquiggle probe when runs a rule inside your app and reports when it held. squiggle probe export keeps the rule as a detector
  • Newsquiggle store audit lists data in your project that came from an app the project doesn't own. --purge removes it
  • Newthe first squiggle up in a project saves a baseline named first
  • Fixsquiggle up gets a development build past the Expo launcher, and reports ready only once the app's JS has connected
  • Fixevery command uses the port from your config or SQUIGGLE_PORT, not always 7777
  • Fixa YAML syntax error in a flow is reported as one, not as "a bug in Squiggle"
  • Fixa Ctrl-C during --matrix or --repair puts the simulator's appearance and text size back
  • Fixa squiggle bench series with a failed run records the failed run and exits 1

Agents & MCP

  • Newreport_card gives your agent the report card
  • Newbisect_state finds the store values that make a flow fail, from two save slots
  • Newwhat_if tells your agent what a flow did under a repeated tap, a Back press or a bad network, from runs already recorded, without touching the app
  • Newtune lists and sets the values your app declared tunable
  • Newproduct_state shows what your app held on each screen
  • Newbranch can start from a save slot, and tries the likeliest alternative first
  • Newpropose_fix turns a --tune or --repair result into a code change
  • Fixan idle squiggle mcp no longer uses a quarter of a CPU core
  • Fixlaunch_app gets past the development launcher and an "Open in …?" alert, and returns once the first screen is up

Flows & device

  • Newflows drive the photo picker, the document picker, the share sheet and permission prompts that iOS shows over your app. Select their controls by the text they show
  • Newsquiggle flow --twin runs a flow on a working network and again on a slow, flaky, cut-off or offline one, and reports what your app did differently, such as a spinner that never goes away or an empty state shown for a server error
  • New--fuzz breaks each endpoint the flow called, one at a time
  • New--race finds a repeated tap or a Back press, made while a request is in flight, that sends a change twice or navigates after the user left. It writes the shortest flow that reproduces each
  • New--chaos runs a flow on a bad network, and --stubs answers the network from an earlier run. A flow can declare chaos in its config
  • New--cache-twins <cold>,<warm> shows which requests a warm app answered from its cache and which it fetched again
  • New--bisect-state <green>,<failing> finds the few store values that make a flow fail, and names the lines that write them and the components that read them
  • New--matrix runs a flow in each simulator setup, such as dark mode and the largest text size, and lists the layout problems each one adds. --repair searches the values you declared tunable for a layout with no problem in any setup
  • New--tune <name> picks a tunable value, such as a list's windowSize, by measuring dropped frames at each one
  • New--cliff VAR=lo..hi finds the list size where dropped frames start to climb, and what rendered most there
  • New--boundaries checks the edges of every control and reports an edge whose touches land on something else
  • New--ax-only finds every control through the accessibility tree alone, the way VoiceOver reaches it
  • Newthree asserts: scroll (frame rate, dropped frames, blank cells), smooth (how a region moves through a transition) and memoryDelta (memory growth since the previous step). Thresholds you leave out come from the screen's budget
  • NewwaitFor waits for a control to appear or go away, so opening a sheet needs no retry
  • Newswipe takes a duration to drag slowly, and a hold to long-press before dragging, so a flow can reorder a list
  • NewsoftKeyboard: true keeps the on-screen keyboard up while a flow types
  • Newa near miss says which part of the selector scored what, and how far under the threshold it fell
  • Fixa selector with a testID and text needs both to match
  • Fixa type step waits for the text to land in the field, and checks it
  • Fixa control whose testID, label or press handler changes in place is found under its new name
  • Fixa scroll longer than its list is several drags inside the list
  • Fixa held drag starts on the control it holds
  • Perfthe wait before each step is 41% shorter, and a relaunch finishes as soon as the app shows its screen

Performance

  • Newset a performance budget per screen in your config
  • Newstartup is split into phases, each timed by the module that owns it
  • Newa JS stall comes with its CPU profile, including the first stall after a fresh launch
  • Newa wait that runs long names the component still animating, with its file and line
  • Newthe js-driven-motion finding catches an animation that moves only while JS runs
  • Fixcapturing a stall profile can no longer crash your app
  • Fixone app launch is one session, whether Studio, the CLI or both watch it
  • Fixsamples follow a relaunched app into its new session
  • Fixa run that opens the performance store while another is writing to it no longer loses its session
  • Fixa long task that repeats is one finding per cause, grouped across sessions

Product analytics

  • Newsplit any report by a state sessions reached, with --where
  • Newsee which app states friction happens in, the states real sessions reach that no flow tests, and how states drift across releases
  • Newan abandoned drag is a friction finding

SDK

  • Newdeclare values Squiggle may tune, such as a list's windowSize, with defineTunable and useTunable
  • Newsave slots capture your Zustand, Legend State and MMKV stores without setup
  • Newstate analytics samples what your app held on each screen, as shapes rather than values. It needs a build variable and the user's consent, set with setStateAnalyticsConsent
  • Fixgestures in your app run as worklets again with the published SDK
  • Fixupgrading Squiggle no longer needs --clear on Metro
  • FixZustand stores appear under their own names, such as useCart
  • Fixa slow drag keeps its interaction until the finger lifts

Website

  • Newevery docs and changelog page has a Markdown copy at its URL plus .md, and each docs page has Copy as Markdown and View as Markdown, for your coding agent
  • Newthe templates page runs each template on the demo device and shows its report card
  • Newon a phone, the menu and the search can be dragged away