What your agent can do

For AI agents: this page is Markdown at https://squiggle.sh/docs/agents/tools.md. Every docs page is listed at https://squiggle.sh/llms.txt, and all of them are one file at https://squiggle.sh/llms-full.txt.

The Squiggle server has ninety tools. Your agent doesn’t need to learn them one by one: they fall into a few jobs, and the kit tells it which to reach for.

The tools, by job

JobTools
Startstatus (what is connected and what works), target (pick the app), briefs (problems the app already found, each with a recording and a source line).
Lookdescribe, find, query, assert, wait_for, inspect, renders, legibility, and screenshot when nothing else will do.
Acttap, hover, input_text, swipe, scroll, scroll_until_visible, back, launch_app, run_flow, and batch to send several at once. tune sets a value the app declared tunable.
Run a journeyrun_intent and the tools that follow a run: intent_wait, resume_intent, steer, intent_stop, intent_continue, approve_action. branch tries several continuations from one point and ranks them.
Rememberlibrary_list, library_save, route, predict, what_if, interface, crawl, invariants, diff_runs, affected_by_diff.
Set up a runfixture (save and restore a named starting point, the same slots as squiggle save and load), deterministic_session (pin the network, animations, clock and locale).
Check your workreport_card, after building a feature: runs the flows that cover the screens you changed and checks their budgets, findings and legibility. It runs offline against recorded stubs unless you pass live: true.
Recordrecord_start, record_stop, replay_recording, filmstrip.
Explainexplain, verify_citations, publish_evidence.
Read the dataEvery perf_ and product_ tool, propose_fix, and probe_read.

Look before acting, cheaply

describe lists what is on screen, controls first, and gives each one a short reference like n42 that tap accepts. After the first look, describe { sinceLastLook: true } returns only what changed. find says whether a selector matches one control, several or none before your agent acts on it, and tap refuses a selector that matches several.

Every acting tool waits for the app to settle and returns what changed on screen in the same reply, so your agent doesn’t need a second look. A successful tap means the tap was sent; to prove it worked, assert the result.

These are the server’s real replies from a checklist screen. Tick an item to see what a tap returns, and compare its size with a full look:

Tap the phone, or
9:41
Checklistguest@acme.com0 / 20 done
Reply: 3,199 characters
MCP
describe {}{  "ok": true,  "data": {    "route": "checklist",    "nodes": [      {"ref":"n42","name":"AXGenericElement","testID":"Checklist","role":"AXGenericElement","native":true},      {"ref":"n43","name":"AXStaticText","role":"AXStaticText","label":"Checklist","native":true},      {"ref":"n44","name":"AXButton","testID":"BackButton","role":"AXButton","label":"(tabs)","native":true,"routerInternal":true,"hint":"router-group segment, not a written label — prefer `back` to navigate back"},      {"ref":"n45","name":"ThemedText","testID":"signed-in-email","text":"guest@acme.com"},      {"ref":"n46","name":"ThemedText","testID":"checklist-progress","text":"0 / 20 done"},      {"ref":"n47","name":"Button","testID":"logout","label":"Log out"},      {"ref":"n48","name":"Pressable","testID":"item-0","role":"checkbox","label":"Item 1"},      {"ref":"n49","name":"Pressable","testID":"item-1","role":"checkbox","label":"Item 2"},      {"ref":"n50","name":"Pressable","testID":"item-2","role":"checkbox","label":"Item 3"},      {"ref":"n51","name":"Pressable","testID":"item-3","role":"checkbox","label":"Item 4"},      {"ref":"n52","name":"Pressable","testID":"item-4","role":"checkbox","label":"Item 5"},      {"ref":"n53","name":"Pressable","testID":"item-5","role":"checkbox","label":"Item 6"},      {"ref":"n54","name":"Pressable","testID":"item-6","role":"checkbox","label":"Item 7"},      {"ref":"n55","name":"Pressable","testID":"item-7","role":"checkbox","label":"Item 8"},      {"ref":"n56","name":"Pressable","testID":"item-8","role":"checkbox","label":"Item 9"},      {"ref":"n57","name":"Pressable","testID":"item-9","role":"checkbox","label":"Item 10"},      {"ref":"n58","name":"Pressable","testID":"item-10","role":"checkbox","label":"Item 11"},      {"ref":"n59","name":"Pressable","testID":"item-11","role":"checkbox","label":"Item 12"},      {"ref":"n60","name":"Pressable","testID":"item-12","role":"checkbox","label":"Item 13"},      {"ref":"n61","name":"Pressable","testID":"item-13","role":"checkbox","label":"Item 14"},      {"ref":"n62","name":"Pressable","testID":"item-14","role":"checkbox","label":"Item 15","offscreen":true},      {"ref":"n63","name":"Pressable","testID":"item-15","role":"checkbox","label":"Item 16","offscreen":true},      {"ref":"n64","name":"Pressable","testID":"item-16","role":"checkbox","label":"Item 17","offscreen":true},      {"ref":"n65","name":"Pressable","testID":"item-17","role":"checkbox","label":"Item 18","offscreen":true},      {"ref":"n66","name":"Pressable","testID":"item-18","role":"checkbox","label":"Item 19","offscreen":true},      {"ref":"n67","name":"Pressable","testID":"item-19","role":"checkbox","label":"Item 20","offscreen":true},      {"ref":"n8","name":"main(RootComponent)"},      {"ref":"n9","name":"AppContainer"},      {"ref":"n10","name":"View"},      {"ref":"n11","name":"View"},      {"ref":"n12","name":"withDevTools(App)"},      {"ref":"n13","name":"App"},      {"ref":"n14","name":"ExpoRoot"},      {"ref":"n15","name":"ContextNavigator"},      {"ref":"n16","name":"NavigationContainerInner"},      {"ref":"n17","name":"BaseNavigationContainer"},      {"ref":"n18","name":"EnsureSingleNavigator"},      {"ref":"n19","name":"ThemeProvider"},      {"ref":"n20","name":"LinkPreviewContextProvider"},      {"ref":"n21","name":"SafeAreaProvider"}    ],    "total": 182,    "omitted": 142,    "evidence": {      "sessionId": "01a137c1-a7af-7fac-9af2-0611f9abc37c",      "eventId": 3350,      "wallMs": 1791939131661    }  }}

From the screen to your code

In a development build, describe { fields: "source" } gives each control’s callSite: the line that renders it, such as src/screens/Login.tsx:42:7. Your agent opens that line instead of searching for a label, and after editing it, find { callSite: "Login.tsx:42" } shows what the line renders now. inspect shows a component’s live props, hooks and state by the names in your source. It only reads; editing props and state is for you, in the Inspector.

Find what re-renders

renders returns the components that re-render most, with the same counts, speeds, times and reasons as Studio’s Renders tab. To measure one interaction, your agent calls renders { reset: true }, uses the app, then calls renders again: counting continues for two minutes after each call. A selector narrows it to one part of the app.

The reply also has cascades (what started each burst of re-renders), loops (components held at loopRate renders a second, 20 unless you set it, for three seconds) and providers (context providers that hand down a new value with the same contents, and the component that renders each one). trends: true adds each component’s last 30 seconds. See Find what re-renders.

Hover a desktop or web app

hover moves an invisible pointer onto a selector, so the element’s hover card, tooltip or highlight appears without your cursor moving. hover { leave: true } moves it off. Read what appeared from the reply’s observed change, or a screenshot. A selector that matches several elements is refused, and so is an element nothing hovers. On macOS, see React Native macOS.

Ask the data a question

probe_read runs a short script against the performance and product data and returns only its result, so your agent doesn’t pull a large table into the conversation to search it:

probe_read
// probe_read: filter on the server, return only what you needconst slow = await perf.sql(`  select name, avg(dur_us) as avg from spans  where kind = 1 group by name order by avg desc limit 5`);const insights = await perf.insights();return { slow, errors: insights.filter((i) => i.severity === 'error').length };

The script can only read. It has no network, no file access and no way to touch the app.

What each tool needs

ClassTools
Free1: status, so your agent can always find out why another tool refused.
Drive28: everything that touches the simulator.
Analyze34: everything that reads stored data or a recording.
Agent27: programs, escalations, approvals, probe_read and propose_fix.

Without a licence, the tools stay listed and refuse when called, with a message your agent can pass on. There is no tool to activate a licence, so a key never ends up in a conversation; see Licence and trial.

Prompts and resources

Two prompts, squiggle-drive-mode and squiggle-perf-mode, hold the working rules for driving and for performance work; a client can pin one instead of your agent fetching it. Resources include squiggle://screen (the current screen, updated as it changes), squiggle://insights/latest, each run as squiggle://run/{runId}, and the eleven kit documents as squiggle://skill/….