
Playwright-inspired DSL for browser automation, enabling reusable UI workflows, locators, network interception, screenshots, session-state handling and an AI-agent command interface for compact control.
Browser automation for Kotlin Multiplatform.
Write a workflow once and run it in Android WebView, iOS WKWebView or JVM Chromium.
Website · Documentation · Examples
A Playwright-inspired Kotlin API for locators, assertions, networking and screenshots, plus compact commands an AI agent can drive the same browser with.
[!NOTE] 0.0.2 alpha. Available on Maven Central. APIs and platform coverage may change.
One dependency in commonMain covers Android, iOS and JVM. Gradle picks the platform variant.
kotlin {
sourceSets {
commonMain.dependencies {
implementation("io.github.bernaferrari:kmpwright-core:0.0.2")
}
}
}Requires mavenCentral(). For the Android Compose wrapper, add
io.github.bernaferrari:kmpwright-compose:0.0.2 to androidMain.
Fill a form, click its button and check the result:
import com.bernaferrari.kmpwright.core.*
suspend fun demo(page: Page) = with(page) {
setContent(demoHtml)
getByLabel("Name").fill("Ada")
getByRole("button", name = "Say hello").click()
expect(getByRole("status")).toHaveText("Hello, Ada!")
}The page shows Hello, Ada! and the assertion passes. Locators wait until an element can be used; assertions wait for the expected result. No server or account needed.
demoHtml, the self-contained pageval demoHtml = """
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>KMPwright demo</title>
<label for="name">Name</label>
<input id="name">
<button onclick="document.getElementById('greeting').textContent =
'Hello, ' + document.getElementById('name').value + '!'">Say hello</button>
<p id="greeting" role="status"></p>
</html>
""".trimIndent()Connect your platform's browser and pass its Page to the shared workflow. Call
suspending APIs from a coroutine, on the main thread for mobile WebViews.
| Android · WebView | iOS · WKWebView | JVM · Chromium |
|---|---|---|
Browser(
AndroidPlatformContext(
activity, webView,
),
).use { browser ->
demo(browser.page())
} |
Browser(
IOSPlatformContext(
webView = webView,
),
).use { browser ->
demo(browser.page())
} |
launchBrowser(
executablePath,
).use { launched ->
demo(
launched.browser.newPage(),
)
} |
| Android 8+ · guide | iOS 15+, arm64 device and simulator · guide | JDK 17+, installed Chrome or a cloud browser · guide |
Features follow each backend's abilities. Check page.capabilities() before an
optional feature; the capability matrix
lists what is partial or missing.
Expose runCommand() as a tool in your LLM SDK. The model reads a snapshot and
acts on element refs, using the agent-browser command subset.
page.runCommand("snapshot -i")
// @e1 [input type="email"]
// @e2 [button] "Sign in"
page.runCommand("fill @e1 ada@example.com")
page.runCommand("click @e2")The example app puts a playground, recipes and an inspector on Android, iPhone and iPad.
KMPwright adapts browser behavior from agent-browser into Kotlin APIs and is independent of Playwright. The upstream comparison records the pinned revision and coverage; no upstream source is included here.
Part of Kotlin Reforge.
Contributing? See development and tests and the release guide. MIT · Third-party notices
Browser automation for Kotlin Multiplatform.
Write a workflow once and run it in Android WebView, iOS WKWebView or JVM Chromium.
Website · Documentation · Examples
A Playwright-inspired Kotlin API for locators, assertions, networking and screenshots, plus compact commands an AI agent can drive the same browser with.
[!NOTE] 0.0.2 alpha. Available on Maven Central. APIs and platform coverage may change.
One dependency in commonMain covers Android, iOS and JVM. Gradle picks the platform variant.
kotlin {
sourceSets {
commonMain.dependencies {
implementation("io.github.bernaferrari:kmpwright-core:0.0.2")
}
}
}Requires mavenCentral(). For the Android Compose wrapper, add
io.github.bernaferrari:kmpwright-compose:0.0.2 to androidMain.
Fill a form, click its button and check the result:
import com.bernaferrari.kmpwright.core.*
suspend fun demo(page: Page) = with(page) {
setContent(demoHtml)
getByLabel("Name").fill("Ada")
getByRole("button", name = "Say hello").click()
expect(getByRole("status")).toHaveText("Hello, Ada!")
}The page shows Hello, Ada! and the assertion passes. Locators wait until an element can be used; assertions wait for the expected result. No server or account needed.
demoHtml, the self-contained pageval demoHtml = """
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>KMPwright demo</title>
<label for="name">Name</label>
<input id="name">
<button onclick="document.getElementById('greeting').textContent =
'Hello, ' + document.getElementById('name').value + '!'">Say hello</button>
<p id="greeting" role="status"></p>
</html>
""".trimIndent()Connect your platform's browser and pass its Page to the shared workflow. Call
suspending APIs from a coroutine, on the main thread for mobile WebViews.
| Android · WebView | iOS · WKWebView | JVM · Chromium |
|---|---|---|
Browser(
AndroidPlatformContext(
activity, webView,
),
).use { browser ->
demo(browser.page())
} |
Browser(
IOSPlatformContext(
webView = webView,
),
).use { browser ->
demo(browser.page())
} |
launchBrowser(
executablePath,
).use { launched ->
demo(
launched.browser.newPage(),
)
} |
| Android 8+ · guide | iOS 15+, arm64 device and simulator · guide | JDK 17+, installed Chrome or a cloud browser · guide |
Features follow each backend's abilities. Check page.capabilities() before an
optional feature; the capability matrix
lists what is partial or missing.
Expose runCommand() as a tool in your LLM SDK. The model reads a snapshot and
acts on element refs, using the agent-browser command subset.
page.runCommand("snapshot -i")
// @e1 [input type="email"]
// @e2 [button] "Sign in"
page.runCommand("fill @e1 ada@example.com")
page.runCommand("click @e2")The example app puts a playground, recipes and an inspector on Android, iPhone and iPad.
KMPwright adapts browser behavior from agent-browser into Kotlin APIs and is independent of Playwright. The upstream comparison records the pinned revision and coverage; no upstream source is included here.
Part of Kotlin Reforge.
Contributing? See development and tests and the release guide. MIT · Third-party notices