Playwright for the entire desktop.
Simulang is a scripting language for automating browsers, native apps, and OS-level workflows — designed to be written with AI agents.
checkout.ts×
invoice.ts
Running
1import { App, AccessibilityTree, AriaRole,2 screenshotFull, GroundingModel } from '@simular-ai/simulib-js'3 4const inst = App.defaultBrowser().open('https://shop.example.com')5const tree = AccessibilityTree.fromPid(inst.pid)6 7// Resolve the buy button via the AX tree8const [btn] = tree.find(AriaRole.Button, 'Add to cart')9tree.activate(btn.refId)10 11// DOM is messy here — fall back to vision12const [x, y] = screenshotFull().ground(13 GroundingModel.default(), 'promo code input',14)15console.log('purchased ✓ $89.40 with promo')Recognized at
- Best paperICLR 2025
- #1OSWorld benchmark
- Top launchProduct Hunt
WHAT IT DOES
One language for every interface.
Simulang lets your AI coding agent express automations as TypeScript that runs reliably across the web, the desktop, and everything in between.
shop.example.com / winter-jacketsresolved 2.3ms
PlumaMenWomenSale⌕winter jacket
BESTSELLERPatagonia Nano Puff$199 $89.40
role=button · name="Add to cart"Add to cartPromoWELCOME10✓Apply
✦ComposerClaude Code
YOU
Watch the homepage and DM me when the new banner ships.
AGENT
const tree = AccessibilityTree.fromForeground()// watch the hero bannersetInterval(() => checkBanner(), 300_000)
Wrote monitor.ts · 1.2sFinderFileEditView23:14
Invoices
Calculator
10.60
=
$simulang run calculator.ts
order #2841invoice.pdf
vision · 0.97Download Invoice
DOM mismatch → vision grounding
HOW IT WORKS
One script. Two ways to see the page.
The accessibility tree is fast and exact. Vision grounding works on pixels when the DOM is unreliable. One script, your choice per step.
invoice.ts
1import { App, AccessibilityTree, AriaRole,2 screenshotFull, GroundingModel } from '@simular-ai/simulib-js'3 4// Open the store and bind the accessibility tree5const inst = App.defaultBrowser().open(6 'https://automationexercise.com'7)8const tree = AccessibilityTree.fromPid(inst.pid)9 10const [link] = tree.find(AriaRole.Link, 'Signup / Login')11tree.activate(link.refId)12tree.setValue(email.refId, process.env.SITE_EMAIL)13tree.activate(submitBtn.refId)14 15// DOM is opaque — fall back to vision grounding16const [x, y] = screenshotFull().ground(17 GroundingModel.default(), 'Download Invoice button',18)19await clickAt(x, y)automationexercise.com
AE
role=search · name="Search"
t-shirtGo
role=button
312 ax-nodes parsedresolved in 34ms
Same script. Different grounding strategy per step — chosen by the runtime, not the author.
GET STARTED
Write your first script in 60 seconds.
TypeScript. Zero boilerplate. Works with Claude Code, Cursor, or whichever coding agent you already use.