{"_id":"@arthurfordllc/slappium","_rev":"2-c1b8aa882bbd7ba590ebde62d60f8583","name":"@arthurfordllc/slappium","dist-tags":{"latest":"2.0.0"},"versions":{"1.0.0":{"name":"@arthurfordllc/slappium","version":"1.0.0","keywords":["ai-agent","testing","cli","ios-testing","appium","ios-simulator","llm","claude","automation","mobile-testing","react-native","xcuitest","ai-testing","developer-tools","typescript"],"author":{"name":"Arthur Ford, LLC"},"license":"MIT","_id":"@arthurfordllc/slappium@1.0.0","maintainers":[{"name":"andygillis","email":"andy@carecoordinate.app"}],"homepage":"https://github.com/arthurfordllc/slappium","bugs":{"url":"https://github.com/arthurfordllc/slappium/issues"},"bin":{"slap":"dist/slap.js","slappium":"dist/slap.js"},"dist":{"shasum":"0923de6b5039bf2109a6a6e064dc94c5035e21f2","tarball":"https://registry.npmjs.org/@arthurfordllc/slappium/-/slappium-1.0.0.tgz","fileCount":6,"integrity":"sha512-KMSEVnGfXCTb2wkPEEoydZ9/mILZxg8YFYL4KYzBgPWX2IxGueLFK6T7TkCWwbZ0DP+MapN5r2mbd7rlkmjBEw==","signatures":[{"sig":"MEUCIQDw3d9r7VwqyzH3J40oMluQ89FZSJHmVsMI7I6QcAsY1gIgfqVd25f3G5pFnm6FZSkY0CLgAVnx8VxtGA0mnPHde1k=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":37035},"type":"module","engines":{"node":">=18"},"gitHead":"d97d2e48a9d7346f029223e573d5a68633f54592","scripts":{"test":"vitest run","build":"esbuild src/index.ts --bundle --platform=node --target=node18 --format=esm --outfile=dist/slap.js --banner:js='#!/usr/bin/env node'","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"andygillis","email":"andy@carecoordinate.app"},"repository":{"url":"git+https://github.com/arthurfordllc/slappium.git","type":"git"},"_npmVersion":"11.9.0","description":"Lightning-fast iOS testing CLI for AI agents. Interact with iOS Simulator apps via Appium + simctl with simple tap/type/assert commands.","directories":{},"_nodeVersion":"25.6.1","_hasShrinkwrap":false,"devDependencies":{"vitest":"^1.6.0","esbuild":"^0.20.0","typescript":"^5.4.0","@types/node":"^25.3.5"},"_npmOperationalInternal":{"tmp":"tmp/slappium_1.0.0_1772979098020_0.8473844878219596","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@arthurfordllc/slappium","version":"2.0.0","description":"Lightning-fast iOS & Android testing CLI for AI agents. Interact with mobile apps via Appium with simple tap/type/assert commands.","type":"module","bin":{"slappium":"dist/slap.js","slap":"dist/slap.js"},"scripts":{"build":"esbuild src/index.ts --bundle --platform=node --target=node18 --format=esm --outfile=dist/slap.js --banner:js='#!/usr/bin/env node'","test":"vitest run","test:watch":"vitest","prepublishOnly":"npm run build"},"keywords":["ai-agent","testing","cli","ios-testing","android-testing","appium","ios-simulator","android-emulator","llm","claude","automation","mobile-testing","react-native","xcuitest","uiautomator2","adb","ai-testing","developer-tools","typescript"],"repository":{"type":"git","url":"git+https://github.com/arthurfordllc/slappium.git"},"homepage":"https://github.com/arthurfordllc/slappium","bugs":{"url":"https://github.com/arthurfordllc/slappium/issues"},"license":"MIT","author":{"name":"Arthur Ford, LLC"},"engines":{"node":">=18"},"devDependencies":{"@types/node":"^25.3.5","esbuild":"^0.20.0","typescript":"^5.4.0","vitest":"^1.6.0"},"gitHead":"d0650b11b098173fcb774898082f4b99689b5081","_id":"@arthurfordllc/slappium@2.0.0","_nodeVersion":"25.6.1","_npmVersion":"11.9.0","dist":{"integrity":"sha512-9UlOFEtTvzLa9+XVVExH68t03NbVndvel37pHuqdLpUO1/SSaWnrdHwUdYwxgsh/vq5la0yE5miaC8r5kGtNxA==","shasum":"dfa95def24fb2d59f91e060cc30117b1b89f166f","tarball":"https://registry.npmjs.org/@arthurfordllc/slappium/-/slappium-2.0.0.tgz","fileCount":7,"unpackedSize":44726,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIBmRtdHZ+ezwwue5fnjcRejLjQFMTY3KILKjMr+sD/PlAiAD6tnA/mi4lVInR1klKBxqvVGaA2TZNLSR3U6f7HFWPA=="}]},"_npmUser":{"name":"andygillis","email":"andy@carecoordinate.app"},"directories":{},"maintainers":[{"name":"andygillis","email":"andy@carecoordinate.app"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/slappium_2.0.0_1773054275041_0.8643111003978681"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-08T14:11:37.902Z","modified":"2026-03-09T11:04:35.316Z","1.0.0":"2026-03-08T14:11:38.167Z","2.0.0":"2026-03-09T11:04:35.186Z"},"bugs":{"url":"https://github.com/arthurfordllc/slappium/issues"},"author":{"name":"Arthur Ford, LLC"},"license":"MIT","homepage":"https://github.com/arthurfordllc/slappium","keywords":["ai-agent","testing","cli","ios-testing","android-testing","appium","ios-simulator","android-emulator","llm","claude","automation","mobile-testing","react-native","xcuitest","uiautomator2","adb","ai-testing","developer-tools","typescript"],"repository":{"type":"git","url":"git+https://github.com/arthurfordllc/slappium.git"},"description":"Lightning-fast iOS & Android testing CLI for AI agents. Interact with mobile apps via Appium with simple tap/type/assert commands.","maintainers":[{"name":"andygillis","email":"andy@carecoordinate.app"}],"readme":"# Slappium\n\n**Lightning-fast iOS & Android testing CLI built for AI agents.**\n\nSlappium gives AI agents (Claude, GPT, Gemini, or any LLM) a dead-simple interface to interact with mobile applications running in the iOS Simulator or Android Emulator. One command to see the screen. One command to tap. One command to type. Zero runtime dependencies -- just a CLI that wraps Appium's REST API into fast, composable commands.\n\n```\nslap peek              # screenshot + element tree -- instant understanding\nslap tap login-button  # tap by testID with auto-wait\nslap type email-input \"user@example.com\"  # type into a field\n```\n\n## Why This Exists\n\nThere was no good way for AI agents to test mobile apps. Maestro has JVM startup overhead on every command. XCUITest/Espresso require compiled test bundles. Raw Appium requires JSON payloads over curl. AI agents need something fundamentally different:\n\n- **One command = one action.** `slap tap login-button`. That's it. No session setup, no JSON, no curl.\n- **`peek` gives you everything.** Screenshot + collapsed element tree in a single call. An AI agent can see the screen and know every `testID` instantly.\n- **Auto-wait on every interaction.** Element not rendered yet? Slappium polls automatically (configurable timeout). No `sleep`. No retry loops.\n- **Rich error messages.** When a `testID` isn't found, the error shows ALL visible `testID`s on screen so you can adapt immediately.\n- **Session auto-recovery.** Appium session expired? Next command silently creates a new one. You never notice.\n- **`type` bypasses the keyboard.** Uses Appium's `setValue` directly on the element. No keyboard dismissal, no hidden buttons, no fighting input quirks.\n- **iOS + Android from the same CLI.** Set `\"platform\": \"android\"` in your config and every command works on Android. Same testIDs, same workflow.\n\n## Stats\n\n| Metric | Value |\n|--------|-------|\n| Source files | 6 |\n| Tests | 69 |\n| Bundle size | 30KB |\n| Runtime deps | 0 |\n| Startup time | ~50ms |\n\n## Quick Start\n\n### Prerequisites\n\n- Node.js 18+\n- [Appium](https://appium.io/) 3+ with the appropriate driver:\n\n**For iOS:**\n```bash\nnpm install -g appium\nappium driver install xcuitest\n```\n- Xcode + iOS Simulator with your app installed (dev build, not Expo Go)\n\n**For Android:**\n```bash\nnpm install -g appium\nappium driver install uiautomator2\n```\n- Android SDK with `ANDROID_HOME` set and `adb` on PATH\n- Android Emulator running with your app installed\n\n**Start Appium:**\n```bash\nappium --port 4723 &\n```\n\n### Install\n\n```bash\nnpm install -g @arthurfordllc/slappium\n```\n\nOr from source:\n```bash\ngit clone https://github.com/arthurfordllc/slappium.git\ncd slappium\nnpm install && npm run build\n```\n\n### Configure\n\nCopy the example config for your platform:\n\n```bash\n# iOS\ncp slappium.config.example.json slappium.config.json\n\n# Android\ncp slappium.config.android.example.json slappium.config.json\n```\n\nEdit `slappium.config.json` with your device UDID, app identifiers, and login credentials.\n\n**Find your device UDID:**\n```bash\n# iOS Simulator\nxcrun simctl list devices booted\n\n# Android Emulator\nadb devices\n```\n\n### Run\n\n```bash\nslap peek\n```\n\n## Configuration\n\n```json\n{\n  \"platform\": \"ios\",\n  \"appiumUrl\": \"http://127.0.0.1:4723\",\n  \"capabilities\": {\n    \"platformName\": \"iOS\",\n    \"appium:automationName\": \"XCUITest\",\n    \"appium:udid\": \"YOUR-SIMULATOR-UDID\",\n    \"appium:bundleId\": \"com.your.app\",\n    \"appium:noReset\": true,\n    \"appium:newCommandTimeout\": 600\n  },\n  \"defaults\": {\n    \"timeout\": 5000,\n    \"pollInterval\": 300,\n    \"screenshotDir\": \"/tmp\",\n    \"maxScrollAttempts\": 10\n  },\n  \"login\": {\n    \"email\": \"test@example.com\",\n    \"password\": \"your-password\",\n    \"otp\": \"123456\"\n  }\n}\n```\n\nSet `\"platform\": \"android\"` and swap `capabilities` for Android:\n\n```json\n{\n  \"platform\": \"android\",\n  \"capabilities\": {\n    \"platformName\": \"Android\",\n    \"appium:automationName\": \"UiAutomator2\",\n    \"appium:udid\": \"emulator-5554\",\n    \"appium:appPackage\": \"com.your.app\",\n    \"appium:appActivity\": \".MainActivity\",\n    \"appium:noReset\": true,\n    \"appium:newCommandTimeout\": 600\n  }\n}\n```\n\n## Commands\n\n### The Big Three (90% of usage)\n\n```bash\nslap peek                                # Screenshot + element tree\nslap tap <testID>                        # Tap by testID with auto-wait\nslap type <testID> <text>                # Clear + type into element\n```\n\n### Interaction\n\n```bash\nslap tap <testID>                        # Tap by React Native testID\nslap tap-text \"<label>\"                  # Tap by visible text label\nslap type <testID> <text>                # Type text (bypasses keyboard)\nslap otp <digits>                        # Enter OTP -- types each digit into otp-digit-0..N\nslap back                                # Navigate back (testID, label, or hardware back)\nslap scroll <up|down>                    # Scroll one page\nslap scroll-to <testID>                  # Scroll down until element found (max 10 attempts)\n```\n\n### Waiting\n\n```bash\nslap wait <testID> [timeout]             # Wait for element to appear\nslap wait-text \"<text>\" [timeout]        # Wait for text on screen\nslap wait-gone <testID> [timeout]        # Wait for element to disappear\n```\n\n### Assertions (exit code 0 = pass, 1 = fail)\n\n```bash\nslap assert <testID>                     # Visible -> exit 0\nslap assert-text \"<text>\"                # Text on screen -> exit 0\nslap assert-not <testID>                 # NOT visible -> exit 0\n```\n\n### Inspection\n\n```bash\nslap peek                                # Screenshot + element tree (THE command)\nslap tree                                # Element tree only\nslap screenshot [name]                   # Screenshot only\nslap source                              # Raw XML page source\nslap inspect <testID>                    # Element details: type, label, value, visible, enabled\nslap find \"<text>\"                       # Find elements by label/value content\n```\n\n### Session & Lifecycle\n\n```bash\nslap session                             # Create/verify Appium session (usually automatic)\nslap status                              # Check if session is alive\nslap login [email] [pass] [otp]          # Full login flow with config defaults\nslap reload                              # Trigger Metro bundle reload\nslap chain \"cmd1\" \"cmd2\" ...             # Run commands sequentially, stop on first failure\n```\n\n## How It Works\n\nSlappium wraps two things into a single CLI:\n\n1. **Appium REST API** -- element finding, tapping, typing, and session management.\n2. **Platform tools** -- `xcrun simctl` (iOS) or `adb` (Android) for screenshots and device control.\n\n### Element Finding\n\nOn iOS, React Native `testID` maps to `accessibilityIdentifier`, which Appium finds via the `accessibility id` locator strategy.\n\nOn Android, React Native `testID` maps to both `resource-id` and `content-desc` depending on the component. Slappium handles this automatically -- it tries `accessibility id` first, then falls back to UiAutomator's `resourceId()` selector.\n\n### Element Tree\n\nThe tree parser takes Appium's verbose 500+ line XML page source and collapses it into ~20 lines of meaningful `testID`s and labels. It auto-detects iOS (XCUITest) vs Android (UiAutomator2) XML format and normalizes both into the same readable output. This is what makes `peek` so powerful for AI agents -- you get a complete, readable summary of the screen in one command.\n\n### Platform Differences (Handled Automatically)\n\n| Feature | iOS | Android |\n|---------|-----|---------|\n| Screenshots | `xcrun simctl` | `adb exec-out screencap` |\n| Back navigation | testID → label → swipe | testID → label → hardware back key |\n| Scrolling | `mobile: scroll` | `mobile: scrollGesture` |\n| Text finding | iOS predicate string | UiAutomator selector |\n| testID locator | `accessibility id` | `accessibility id` + `resourceId()` fallback |\n| Reload | Shake gesture | Menu key (keyevent 82) |\n| Session file | `/tmp/slappium-ios-session.json` | `/tmp/slappium-android-session.json` |\n\n### Key Design Decisions\n\n- **No keyboard interaction.** `type` uses Appium's `setValue` API directly, bypassing the on-screen keyboard entirely.\n- **Session persistence.** The Appium session ID is saved per-platform to `/tmp/slappium-{platform}-session.json`. Subsequent commands reuse it. If the session is dead, a new one is created automatically.\n- **Custom XML parser.** Zero-dependency recursive descent parser handles both iOS and Android XML formats without any XML library.\n\n## For AI Agent Developers\n\nIf you're building an AI agent that needs to interact with mobile apps, Slappium is designed for you. Here's the typical workflow:\n\n```bash\n# 1. See what's on screen\nslap peek\n# -> saves screenshot to /tmp, prints element tree with all testIDs\n\n# 2. Interact\nslap tap login-button\nslap type email-input \"user@test.com\"\nslap type password-input \"Password123\"\nslap tap submit-btn\n\n# 3. Handle OTP (one command!)\nslap wait otp-digit-0 10000\nslap otp 123456\nslap tap verify-btn\n\n# 4. Verify navigation\nslap wait-gone otp-digit-0 15000\nslap assert-text \"Welcome\"\n\n# 5. See the new state\nslap peek\n```\n\nEvery command is stateless (connects, acts, exits). Exit codes are meaningful (0 = success, 1 = element not found / assertion failed, 2 = error). Output is concise and parseable. This is what AI agents need.\n\n### Works With\n\n- **React Native / Expo** -- `testID` prop works on both iOS and Android\n- **Native iOS** -- SwiftUI `.accessibilityIdentifier()`, UIKit `accessibilityIdentifier`\n- **Native Android** -- `android:contentDescription`, `resource-id`\n- **Any framework** that sets accessibility identifiers\n\n## Tests\n\n```bash\nnpm test            # Run all 69 tests\nnpm run test:watch  # Watch mode\n```\n\n## License\n\nMIT -- see [LICENSE](LICENSE).\n\n## Built by\n\n[Arthur Ford, LLC](https://github.com/arthurfordllc)\n","readmeFilename":"README.md"}