Files
sanderling/docs/manual/getting-started.md
T
pj 776becdf4b Remove in-app SDK (#43)
* chore: delete internal/agent package

* chore(build): remove sdk-android from gradle settings

* chore(makefile): remove sdk-android targets

* chore(ci): remove release-android job from release workflow

* chore(folio): remove sdk-android dependency

* chore(folio): remove SDK initialization from FolioApplication

* chore(folio): delete snapshot extractor files

* feat(folio): add balance to account card content description

* feat(folio): add hierarchy content descriptions to LedgerScreen

* refactor(folio): rewrite spec.ts to use ax extractors

* docs: remove in-app SDK from README

* feat(folio): add focused_input indicator to App

* docs: remove in-app SDK from index

* refactor(runner): remove agent SDK connection and snapshot step

* test(runner): update tests for SDK removal

* docs: remove Android SDK section from getting-started

* refactor(testrun): remove agent SDK connection setup

* docs: remove snapshots from writing-specs

* docs: remove in-app SDK from architecture doc

* docs(folio): update README for SDK removal

* docs: update per-step cycle diagram in architecture doc

* fix(folio): detect screens from unique element presence, not id: selectors

testTag() in Compose is not exposed as resource-id without testTagsAsResourceId.
Use desc: selectors for elements unique to each screen instead of id: path queries.

* feat(folio): add screen root contentDescription for scoped ax selection

Each screen root gets semantics { contentDescription = "ScreenName" } so
sanderling specs can scope element lookups through the screen: desc:LoginScreen > desc:login_submit.

* fix(folio): scope all ax selectors through screen root nodes

Use desc:ScreenName > desc:element path queries so every selector is
rooted at the screen level. focusedInput stays unscoped since it lives
in the app root, outside any screen.

* fix(folio): guard newAccountBalanceIsZero against navigation false positives

Scoped selectors return [] when not on HomeScreen so accounts vanish and
reappear as apparently-new on each visit. Skip the check when prev was empty.

* chore(folio): link @sanderling/spec to local pkg/spec for IDE type checking

* feat(spec): add desc, class, clickable, enabled, checked, focused, selected to AccessibilityElement

Runtime fields set by the verifier were missing from the TypeScript type,
causing linting errors on el.desc and related accesses in specs.

* chore(folio): switch to bun, add tsconfig.json for IDE type checking

- Remove package-lock.json, add bun.lock
- Add tsconfig.json so VSCode resolves @sanderling/spec types
- Fix parseAccount/parseLedgerRow to accept string | undefined
2026-04-25 20:04:29 +07:00

1.7 KiB

title
title
Getting started

Getting started

Install the CLI, run a spec.

Prerequisites

Android / iOS:

  • An Android emulator with API level 30 or newer (or a connected device).
  • adb on your PATH.

Web:

  • Chrome installed. sanderling drives it via CDP; no other setup required.

Run sanderling doctor to check the host environment.

Install

CLI

curl -fsSL https://raw.githubusercontent.com/priyanshujain/sanderling/master/install.sh | bash

Spec package (npm)

npm install --save-dev @sanderling/spec

Your first run

Android

The repo ships a working sample at examples/folio, a Kotlin Multiplatform app with a TypeScript spec under sanderling/spec.ts. Install just, then from examples/folio:

just install   # build and install the folio APK on a booted emulator or device
just test      # run the spec

With no device connected and multiple AVDs, pick one:

AVD=Pixel_7 just test

Persistent settings can live in a .env alongside the justfile (AVD=Pixel_7, DURATION=5m, and so on).

Web

The repo also ships a web sample at examples/folio-web, a React/Vite app with the same domain logic. From examples/folio-web:

just test      # starts Chrome, runs the spec

No emulator or SDK setup needed.

Trace output

When the run ends, the trace lands in sanderling/runs/<timestamp>/:

runs/2026-04-18T12-34-56/
├── trace.jsonl
├── screenshots/
└── meta.json

Browse it with sanderling inspect (see inspect), or read trace.jsonl step by step.

Next: writing specs.