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 --tuneand--repairmeasured 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 flowdoes - 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
appsin.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 toapps - 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_UDIDorudidin your config. Your agent's tools refuse the same way - New
squiggle cardchecks 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 - New
squiggle add screenwrites a new screen from one of six templates, with a flow that drives it and a renders budget it meets - New
squiggle saveandsquiggle loadkeep the screen the app is on, with the data behind it, and put it back in under a second instead of tapping through screens - New
squiggle bisectfinds the commit that slowed a flow, without rebuilding the app.--hunkssays how much of the slowdown each change in that commit accounts for - New
squiggle bakeoffruns one flow against several revisions and compares pass rate, duration, renders, dropped frames, memory growth and startup in one table - New
squiggle motionrecords how a view moves after a tap and gives you thewithSpringconfig that reproduces it - New
squiggle contracts proposeturns what your passing runs always showed into asserts in your flows, and proposes removing an assert that stopped holding - New
squiggle perf budgetchecks each screen's budget against the newest session, with the margin to each limit.--changedchecks only the screens your branch changed - New
squiggle perf labelsexports every run with its outcome, heals and app state, as JSONL - New
squiggle probe whenruns a rule inside your app and reports when it held.squiggle probe exportkeeps the rule as a detector - New
squiggle store auditlists data in your project that came from an app the project doesn't own.--purgeremoves it - Newthe first
squiggle upin a project saves a baseline namedfirst - Fix
squiggle upgets 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
--matrixor--repairputs the simulator's appearance and text size back - Fixa
squiggle benchseries with a failed run records the failed run and exits 1
Agents & MCP
- New
report_cardgives your agent the report card - New
bisect_statefinds the store values that make a flow fail, from two save slots - New
what_iftells 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 - New
tunelists and sets the values your app declared tunable - New
product_stateshows what your app held on each screen - New
branchcan start from a save slot, and tries the likeliest alternative first - New
propose_fixturns a--tuneor--repairresult into a code change - Fixan idle
squiggle mcpno longer uses a quarter of a CPU core - Fix
launch_appgets 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
- New
squiggle flow --twinruns 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
--fuzzbreaks each endpoint the flow called, one at a time - New
--racefinds 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
--chaosruns a flow on a bad network, and--stubsanswers the network from an earlier run. A flow can declarechaosin 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
--matrixruns a flow in each simulator setup, such as dark mode and the largest text size, and lists the layout problems each one adds.--repairsearches 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'swindowSize, by measuring dropped frames at each one - New
--cliff VAR=lo..hifinds the list size where dropped frames start to climb, and what rendered most there - New
--boundarieschecks the edges of every control and reports an edge whose touches land on something else - New
--ax-onlyfinds 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) andmemoryDelta(memory growth since the previous step). Thresholds you leave out come from the screen's budget - New
waitForwaits for a control to appear or go away, so opening a sheet needs no retry - New
swipetakes adurationto drag slowly, and aholdto long-press before dragging, so a flow can reorder a list - New
softKeyboard: truekeeps 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
testIDandtextneeds both to match - Fixa
typestep 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-motionfinding 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, withdefineTunableanduseTunable - 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
--clearon 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