# How Squiggle works

Squiggle has a part in your app and a part on your Mac. When you write tests, one rule matters most: a step that passes was sent, which is not the same as working.

## The SDK, in your app

The SDK is the `@squiggle.sh/react-native` package. While your app runs, it keeps a live model of it: every component on screen, what rendered and why, store changes, network requests, the current screen, and what each tap set off. The docs call this model the **runtime graph**.

Everything else in Squiggle reads that model. A flow finds the Add to cart button in it, Studio draws it, and a performance finding points at a component in it. If the SDK isn’t in your app build, Squiggle has nothing to read, so setup starts there.

The SDK only records while something on your Mac is connected to it. With nothing connected, it stays idle and costs close to nothing.

## Studio and the CLI, on your Mac

**Studio** is the desktop app. It shows your simulator, the Inspector, performance and analytics, and it records and replays flows. The **CLI** is the `squiggle` command. It runs flows in your terminal and in CI, and it includes the MCP server that lets a coding agent drive your app.

Both talk to the same app, and both keep their files in one `.squiggle/` folder at your project root, so a flow recorded in Studio runs from the terminal unchanged. The [Project folder](https://squiggle.sh/docs/reference/project) page lists what’s in it and what to commit.

To drive the simulator quickly, Squiggle needs your app launched with Squiggle attached. Studio and `squiggle up` launch it that way. If you launch the app from Xcode instead, flows still run, only more slowly. [Troubleshooting](https://squiggle.sh/docs/troubleshooting) explains how to tell.

## A passing step was sent, not proven

When a flow taps a button, the step passes once the tap reaches the button. It doesn’t check that the app reacted. If the button is broken, the tap still passes, and Squiggle prints a warning when nothing in the app changed afterwards.

To check that something happened, add an `assert` after the action. An assert looks at the screen again and fails when the result isn’t there. Try both versions of the same flow against a broken Add to cart button:

End every journey with an assert about what someone using your app should see. The [flows](https://squiggle.sh/docs/flows) page covers the kinds of assert you can write.
