lim 0.1.5 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +836 -0
- package/bin/dev.js +16 -0
- package/bin/run.js +63 -0
- package/dist/base-command.d.ts +51 -0
- package/dist/base-command.d.ts.map +1 -0
- package/dist/base-command.js +441 -0
- package/dist/base-command.js.map +1 -0
- package/dist/commands/android/connect.d.ts +17 -0
- package/dist/commands/android/connect.d.ts.map +1 -0
- package/dist/commands/android/connect.js +50 -0
- package/dist/commands/android/connect.js.map +1 -0
- package/dist/commands/android/create.d.ts +25 -0
- package/dist/commands/android/create.d.ts.map +1 -0
- package/dist/commands/android/create.js +202 -0
- package/dist/commands/android/create.js.map +1 -0
- package/dist/commands/android/delete.d.ts +17 -0
- package/dist/commands/android/delete.d.ts.map +1 -0
- package/dist/commands/android/delete.js +44 -0
- package/dist/commands/android/delete.js.map +1 -0
- package/dist/commands/android/element-tree.d.ts +16 -0
- package/dist/commands/android/element-tree.d.ts.map +1 -0
- package/dist/commands/android/element-tree.js +60 -0
- package/dist/commands/android/element-tree.js.map +1 -0
- package/dist/commands/android/find-element.d.ts +28 -0
- package/dist/commands/android/find-element.d.ts.map +1 -0
- package/dist/commands/android/find-element.js +70 -0
- package/dist/commands/android/find-element.js.map +1 -0
- package/dist/commands/android/get.d.ts +17 -0
- package/dist/commands/android/get.d.ts.map +1 -0
- package/dist/commands/android/get.js +43 -0
- package/dist/commands/android/get.js.map +1 -0
- package/dist/commands/android/install-app.d.ts +18 -0
- package/dist/commands/android/install-app.d.ts.map +1 -0
- package/dist/commands/android/install-app.js +70 -0
- package/dist/commands/android/install-app.js.map +1 -0
- package/dist/commands/android/list.d.ts +19 -0
- package/dist/commands/android/list.d.ts.map +1 -0
- package/dist/commands/android/list.js +61 -0
- package/dist/commands/android/list.js.map +1 -0
- package/dist/commands/android/open-url.d.ts +18 -0
- package/dist/commands/android/open-url.d.ts.map +1 -0
- package/dist/commands/android/open-url.js +51 -0
- package/dist/commands/android/open-url.js.map +1 -0
- package/dist/commands/android/press-key.d.ts +19 -0
- package/dist/commands/android/press-key.d.ts.map +1 -0
- package/dist/commands/android/press-key.js +52 -0
- package/dist/commands/android/press-key.js.map +1 -0
- package/dist/commands/android/record.d.ts +22 -0
- package/dist/commands/android/record.d.ts.map +1 -0
- package/dist/commands/android/record.js +100 -0
- package/dist/commands/android/record.js.map +1 -0
- package/dist/commands/android/screenshot.d.ts +18 -0
- package/dist/commands/android/screenshot.d.ts.map +1 -0
- package/dist/commands/android/screenshot.js +66 -0
- package/dist/commands/android/screenshot.js.map +1 -0
- package/dist/commands/android/scroll.d.ts +32 -0
- package/dist/commands/android/scroll.d.ts.map +1 -0
- package/dist/commands/android/scroll.js +72 -0
- package/dist/commands/android/scroll.js.map +1 -0
- package/dist/commands/android/tap-element.d.ts +27 -0
- package/dist/commands/android/tap-element.d.ts.map +1 -0
- package/dist/commands/android/tap-element.js +60 -0
- package/dist/commands/android/tap-element.js.map +1 -0
- package/dist/commands/android/tap.d.ts +25 -0
- package/dist/commands/android/tap.d.ts.map +1 -0
- package/dist/commands/android/tap.js +55 -0
- package/dist/commands/android/tap.js.map +1 -0
- package/dist/commands/android/type.d.ts +31 -0
- package/dist/commands/android/type.d.ts.map +1 -0
- package/dist/commands/android/type.js +53 -0
- package/dist/commands/android/type.js.map +1 -0
- package/dist/commands/asset/delete.d.ts +17 -0
- package/dist/commands/asset/delete.d.ts.map +1 -0
- package/dist/commands/asset/delete.js +23 -0
- package/dist/commands/asset/delete.js.map +1 -0
- package/dist/commands/asset/list.d.ts +22 -0
- package/dist/commands/asset/list.d.ts.map +1 -0
- package/dist/commands/asset/list.js +97 -0
- package/dist/commands/asset/list.js.map +1 -0
- package/dist/commands/asset/pull.d.ts +19 -0
- package/dist/commands/asset/pull.d.ts.map +1 -0
- package/dist/commands/asset/pull.js +84 -0
- package/dist/commands/asset/pull.js.map +1 -0
- package/dist/commands/asset/push.d.ts +18 -0
- package/dist/commands/asset/push.d.ts.map +1 -0
- package/dist/commands/asset/push.js +43 -0
- package/dist/commands/asset/push.js.map +1 -0
- package/dist/commands/ios/app-log.d.ts +20 -0
- package/dist/commands/ios/app-log.d.ts.map +1 -0
- package/dist/commands/ios/app-log.js +86 -0
- package/dist/commands/ios/app-log.js.map +1 -0
- package/dist/commands/ios/cp.d.ts +19 -0
- package/dist/commands/ios/cp.d.ts.map +1 -0
- package/dist/commands/ios/cp.js +64 -0
- package/dist/commands/ios/cp.js.map +1 -0
- package/dist/commands/ios/create.d.ts +25 -0
- package/dist/commands/ios/create.d.ts.map +1 -0
- package/dist/commands/ios/create.js +165 -0
- package/dist/commands/ios/create.js.map +1 -0
- package/dist/commands/ios/delete.d.ts +17 -0
- package/dist/commands/ios/delete.d.ts.map +1 -0
- package/dist/commands/ios/delete.js +44 -0
- package/dist/commands/ios/delete.js.map +1 -0
- package/dist/commands/ios/element-tree.d.ts +16 -0
- package/dist/commands/ios/element-tree.d.ts.map +1 -0
- package/dist/commands/ios/element-tree.js +57 -0
- package/dist/commands/ios/element-tree.js.map +1 -0
- package/dist/commands/ios/get.d.ts +17 -0
- package/dist/commands/ios/get.d.ts.map +1 -0
- package/dist/commands/ios/get.js +44 -0
- package/dist/commands/ios/get.js.map +1 -0
- package/dist/commands/ios/info.d.ts +16 -0
- package/dist/commands/ios/info.d.ts.map +1 -0
- package/dist/commands/ios/info.js +55 -0
- package/dist/commands/ios/info.js.map +1 -0
- package/dist/commands/ios/install-app.d.ts +20 -0
- package/dist/commands/ios/install-app.d.ts.map +1 -0
- package/dist/commands/ios/install-app.js +97 -0
- package/dist/commands/ios/install-app.js.map +1 -0
- package/dist/commands/ios/launch-app.d.ts +23 -0
- package/dist/commands/ios/launch-app.d.ts.map +1 -0
- package/dist/commands/ios/launch-app.js +74 -0
- package/dist/commands/ios/launch-app.js.map +1 -0
- package/dist/commands/ios/list-apps.d.ts +16 -0
- package/dist/commands/ios/list-apps.d.ts.map +1 -0
- package/dist/commands/ios/list-apps.js +51 -0
- package/dist/commands/ios/list-apps.js.map +1 -0
- package/dist/commands/ios/list.d.ts +19 -0
- package/dist/commands/ios/list.d.ts.map +1 -0
- package/dist/commands/ios/list.js +61 -0
- package/dist/commands/ios/list.js.map +1 -0
- package/dist/commands/ios/lsof.d.ts +16 -0
- package/dist/commands/ios/lsof.d.ts.map +1 -0
- package/dist/commands/ios/lsof.js +47 -0
- package/dist/commands/ios/lsof.js.map +1 -0
- package/dist/commands/ios/open-url.d.ts +18 -0
- package/dist/commands/ios/open-url.d.ts.map +1 -0
- package/dist/commands/ios/open-url.js +51 -0
- package/dist/commands/ios/open-url.js.map +1 -0
- package/dist/commands/ios/perform.d.ts +18 -0
- package/dist/commands/ios/perform.d.ts.map +1 -0
- package/dist/commands/ios/perform.js +228 -0
- package/dist/commands/ios/perform.js.map +1 -0
- package/dist/commands/ios/press-key.d.ts +19 -0
- package/dist/commands/ios/press-key.d.ts.map +1 -0
- package/dist/commands/ios/press-key.js +52 -0
- package/dist/commands/ios/press-key.js.map +1 -0
- package/dist/commands/ios/record.d.ts +22 -0
- package/dist/commands/ios/record.d.ts.map +1 -0
- package/dist/commands/ios/record.js +101 -0
- package/dist/commands/ios/record.js.map +1 -0
- package/dist/commands/ios/reverse.d.ts +19 -0
- package/dist/commands/ios/reverse.d.ts.map +1 -0
- package/dist/commands/ios/reverse.js +97 -0
- package/dist/commands/ios/reverse.js.map +1 -0
- package/dist/commands/ios/screenshot.d.ts +18 -0
- package/dist/commands/ios/screenshot.d.ts.map +1 -0
- package/dist/commands/ios/screenshot.js +65 -0
- package/dist/commands/ios/screenshot.js.map +1 -0
- package/dist/commands/ios/scroll.d.ts +19 -0
- package/dist/commands/ios/scroll.d.ts.map +1 -0
- package/dist/commands/ios/scroll.js +57 -0
- package/dist/commands/ios/scroll.js.map +1 -0
- package/dist/commands/ios/simctl.d.ts +17 -0
- package/dist/commands/ios/simctl.d.ts.map +1 -0
- package/dist/commands/ios/simctl.js +72 -0
- package/dist/commands/ios/simctl.js.map +1 -0
- package/dist/commands/ios/sync.d.ts +23 -0
- package/dist/commands/ios/sync.d.ts.map +1 -0
- package/dist/commands/ios/sync.js +90 -0
- package/dist/commands/ios/sync.js.map +1 -0
- package/dist/commands/ios/syslog.d.ts +16 -0
- package/dist/commands/ios/syslog.d.ts.map +1 -0
- package/dist/commands/ios/syslog.js +62 -0
- package/dist/commands/ios/syslog.js.map +1 -0
- package/dist/commands/ios/tap-element.d.ts +23 -0
- package/dist/commands/ios/tap-element.d.ts.map +1 -0
- package/dist/commands/ios/tap-element.js +92 -0
- package/dist/commands/ios/tap-element.js.map +1 -0
- package/dist/commands/ios/tap.d.ts +25 -0
- package/dist/commands/ios/tap.d.ts.map +1 -0
- package/dist/commands/ios/tap.js +55 -0
- package/dist/commands/ios/tap.js.map +1 -0
- package/dist/commands/ios/terminate-app.d.ts +18 -0
- package/dist/commands/ios/terminate-app.d.ts.map +1 -0
- package/dist/commands/ios/terminate-app.js +49 -0
- package/dist/commands/ios/terminate-app.js.map +1 -0
- package/dist/commands/ios/toggle-keyboard.d.ts +15 -0
- package/dist/commands/ios/toggle-keyboard.d.ts.map +1 -0
- package/dist/commands/ios/toggle-keyboard.js +45 -0
- package/dist/commands/ios/toggle-keyboard.js.map +1 -0
- package/dist/commands/ios/type.d.ts +19 -0
- package/dist/commands/ios/type.d.ts.map +1 -0
- package/dist/commands/ios/type.js +53 -0
- package/dist/commands/ios/type.js.map +1 -0
- package/dist/commands/ios/xcodebuild.d.ts +17 -0
- package/dist/commands/ios/xcodebuild.d.ts.map +1 -0
- package/dist/commands/ios/xcodebuild.js +59 -0
- package/dist/commands/ios/xcodebuild.js.map +1 -0
- package/dist/commands/ios/xcrun.d.ts +17 -0
- package/dist/commands/ios/xcrun.d.ts.map +1 -0
- package/dist/commands/ios/xcrun.js +60 -0
- package/dist/commands/ios/xcrun.js.map +1 -0
- package/dist/commands/login.d.ts +14 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +22 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +14 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +18 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/session/start.d.ts +16 -0
- package/dist/commands/session/start.d.ts.map +1 -0
- package/dist/commands/session/start.js +129 -0
- package/dist/commands/session/start.js.map +1 -0
- package/dist/commands/session/status.d.ts +14 -0
- package/dist/commands/session/status.d.ts.map +1 -0
- package/dist/commands/session/status.js +65 -0
- package/dist/commands/session/status.js.map +1 -0
- package/dist/commands/session/stop.d.ts +18 -0
- package/dist/commands/session/stop.d.ts.map +1 -0
- package/dist/commands/session/stop.js +76 -0
- package/dist/commands/session/stop.js.map +1 -0
- package/dist/commands/skills/install.d.ts +18 -0
- package/dist/commands/skills/install.d.ts.map +1 -0
- package/dist/commands/skills/install.js +473 -0
- package/dist/commands/skills/install.js.map +1 -0
- package/dist/commands/xcode/attach-simulator.d.ts +18 -0
- package/dist/commands/xcode/attach-simulator.d.ts.map +1 -0
- package/dist/commands/xcode/attach-simulator.js +55 -0
- package/dist/commands/xcode/attach-simulator.js.map +1 -0
- package/dist/commands/xcode/build.d.ts +35 -0
- package/dist/commands/xcode/build.d.ts.map +1 -0
- package/dist/commands/xcode/build.js +192 -0
- package/dist/commands/xcode/build.js.map +1 -0
- package/dist/commands/xcode/create.d.ts +22 -0
- package/dist/commands/xcode/create.d.ts.map +1 -0
- package/dist/commands/xcode/create.js +189 -0
- package/dist/commands/xcode/create.js.map +1 -0
- package/dist/commands/xcode/delete.d.ts +17 -0
- package/dist/commands/xcode/delete.d.ts.map +1 -0
- package/dist/commands/xcode/delete.js +44 -0
- package/dist/commands/xcode/delete.js.map +1 -0
- package/dist/commands/xcode/get.d.ts +17 -0
- package/dist/commands/xcode/get.d.ts.map +1 -0
- package/dist/commands/xcode/get.js +59 -0
- package/dist/commands/xcode/get.js.map +1 -0
- package/dist/commands/xcode/list.d.ts +18 -0
- package/dist/commands/xcode/list.d.ts.map +1 -0
- package/dist/commands/xcode/list.js +58 -0
- package/dist/commands/xcode/list.js.map +1 -0
- package/dist/commands/xcode/sync.d.ts +24 -0
- package/dist/commands/xcode/sync.d.ts.map +1 -0
- package/dist/commands/xcode/sync.js +93 -0
- package/dist/commands/xcode/sync.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/additional-files.d.ts +6 -0
- package/dist/lib/additional-files.d.ts.map +1 -0
- package/dist/lib/additional-files.js +19 -0
- package/dist/lib/additional-files.js.map +1 -0
- package/dist/lib/android-selector.d.ts +50 -0
- package/dist/lib/android-selector.d.ts.map +1 -0
- package/dist/lib/android-selector.js +103 -0
- package/dist/lib/android-selector.js.map +1 -0
- package/dist/lib/auth.d.ts +2 -0
- package/dist/lib/auth.d.ts.map +1 -0
- package/dist/lib/auth.js +60 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/config.d.ts +65 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +290 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/daemon-client.d.ts +9 -0
- package/dist/lib/daemon-client.d.ts.map +1 -0
- package/dist/lib/daemon-client.js +81 -0
- package/dist/lib/daemon-client.js.map +1 -0
- package/dist/lib/daemon.d.ts +41 -0
- package/dist/lib/daemon.d.ts.map +1 -0
- package/dist/lib/daemon.js +511 -0
- package/dist/lib/daemon.js.map +1 -0
- package/dist/lib/detox-version.d.ts +12 -0
- package/dist/lib/detox-version.d.ts.map +1 -0
- package/dist/lib/detox-version.js +30 -0
- package/dist/lib/detox-version.js.map +1 -0
- package/dist/lib/duration.d.ts +2 -0
- package/dist/lib/duration.d.ts.map +1 -0
- package/dist/lib/duration.js +37 -0
- package/dist/lib/duration.js.map +1 -0
- package/dist/lib/formatting.d.ts +3 -0
- package/dist/lib/formatting.d.ts.map +1 -0
- package/dist/lib/formatting.js +31 -0
- package/dist/lib/formatting.js.map +1 -0
- package/dist/lib/ignore-patterns.d.ts +2 -0
- package/dist/lib/ignore-patterns.d.ts.map +1 -0
- package/dist/lib/ignore-patterns.js +18 -0
- package/dist/lib/ignore-patterns.js.map +1 -0
- package/dist/lib/instance-client-factory.d.ts +29 -0
- package/dist/lib/instance-client-factory.d.ts.map +1 -0
- package/dist/lib/instance-client-factory.js +87 -0
- package/dist/lib/instance-client-factory.js.map +1 -0
- package/dist/lib/launch-app-runtime.d.ts +23 -0
- package/dist/lib/launch-app-runtime.d.ts.map +1 -0
- package/dist/lib/launch-app-runtime.js +58 -0
- package/dist/lib/launch-app-runtime.js.map +1 -0
- package/dist/lib/remote-skills.d.ts +47 -0
- package/dist/lib/remote-skills.d.ts.map +1 -0
- package/dist/lib/remote-skills.js +241 -0
- package/dist/lib/remote-skills.js.map +1 -0
- package/dist/lib/reverse-port-mapping.d.ts +6 -0
- package/dist/lib/reverse-port-mapping.d.ts.map +1 -0
- package/dist/lib/reverse-port-mapping.js +24 -0
- package/dist/lib/reverse-port-mapping.js.map +1 -0
- package/dist/lib/skills.d.ts +17 -0
- package/dist/lib/skills.d.ts.map +1 -0
- package/dist/lib/skills.js +153 -0
- package/dist/lib/skills.js.map +1 -0
- package/package.json +69 -13
- package/.npmignore +0 -2
- package/build/lib/index.js +0 -1498
- package/build/lib/index.map +0 -1
- package/build/lib/utils/courier.js +0 -98
- package/build/lib/utils/courier.map +0 -1
- package/build/lib/utils/polyfill.js +0 -53
- package/build/lib/utils/polyfill.map +0 -1
- package/build.sh +0 -9
- package/index.js +0 -2
- package/lib/index.js +0 -284
- package/lib/utils/courier.js +0 -108
- package/lib/utils/polyfill.js +0 -42
- package/native.js +0 -2
package/README.md
ADDED
|
@@ -0,0 +1,836 @@
|
|
|
1
|
+
# lim
|
|
2
|
+
|
|
3
|
+
The official command-line interface for [Limrun](https://limrun.com) — create and control cloud mobile sandboxes for Android, iOS, and Xcode.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# npm
|
|
9
|
+
npm install -g lim
|
|
10
|
+
|
|
11
|
+
# npx (no install)
|
|
12
|
+
npx lim <command>
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### Migrating from `@limrun/cli`
|
|
16
|
+
|
|
17
|
+
`lim` is the canonical npm package for the Limrun CLI. If you already installed the older scoped package, remove it before installing `lim` so npm does not hit a global `lim` binary conflict:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm uninstall -g @limrun/cli
|
|
21
|
+
npm install -g lim
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
If you already have the `lim` package installed globally, update it with:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install -g lim
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Authentication
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Log in via browser (stores API key in ~/.lim/config.yaml)
|
|
34
|
+
lim login
|
|
35
|
+
|
|
36
|
+
# Or provide an API key directly
|
|
37
|
+
lim --api-key <YOUR_KEY> android list
|
|
38
|
+
|
|
39
|
+
# Or use an environment variable
|
|
40
|
+
export LIM_API_KEY=<YOUR_KEY>
|
|
41
|
+
lim android list
|
|
42
|
+
|
|
43
|
+
# Log out (removes stored API key)
|
|
44
|
+
lim logout
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The CLI stores configuration in `~/.lim/config.yaml`. This file is compatible with the Go-based `lim` CLI — if you've already logged in with the Go version, the TypeScript CLI will use the same credentials.
|
|
48
|
+
|
|
49
|
+
## Global Flags
|
|
50
|
+
|
|
51
|
+
Most commands support these flags (exceptions: `lim skills install` does not take `--api-key` because it does not talk to the API):
|
|
52
|
+
|
|
53
|
+
| Flag | Description |
|
|
54
|
+
| ------------------- | ---------------------------------------------------------- |
|
|
55
|
+
| `--api-key <value>` | API key (also reads `LIM_API_KEY` env var) |
|
|
56
|
+
| `--json` | Output as JSON instead of human-readable tables |
|
|
57
|
+
| `--quiet` | Suppress intermediate logs and print only the final result |
|
|
58
|
+
| `--help` | Show help for any command |
|
|
59
|
+
|
|
60
|
+
## Command Structure
|
|
61
|
+
|
|
62
|
+
Commands are organized by resource (noun-first), so you can discover everything available for a platform with `--help`:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
lim ios --help # All iOS commands
|
|
66
|
+
lim android --help # All Android commands
|
|
67
|
+
lim xcode --help # All Xcode commands
|
|
68
|
+
lim asset --help # All asset commands
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Instance ID is optional** on interaction commands. When omitted, the CLI uses the last created instance of the matching type:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
lim ios create # Creates ios_abc123, remembers it
|
|
75
|
+
lim ios screenshot test.png # Uses ios_abc123 automatically
|
|
76
|
+
lim ios tap 100 200 # Still uses ios_abc123
|
|
77
|
+
lim session start # Starts session for ios_abc123
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
You can always provide an ID explicitly to target a specific instance:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
lim ios screenshot test.png --id ios_def456
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
For repeatable scripts and LLM agents, prefer explicit platform commands plus an explicit `--id` once you have it:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
lim ios get ios_abc123 --json
|
|
90
|
+
lim ios screenshot screenshot.png --id ios_abc123
|
|
91
|
+
lim android tap --id android_abc123 100 200
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
This avoids relying on locally cached "last created" state and keeps the target platform explicit.
|
|
95
|
+
|
|
96
|
+
## Commands
|
|
97
|
+
|
|
98
|
+
- [iOS](#ios) — Create, manage, and interact with iOS instances
|
|
99
|
+
- [Android](#android) — Create, manage, and interact with Android instances
|
|
100
|
+
- [Xcode](#xcode) — Create and manage Xcode sandbox instances
|
|
101
|
+
- [Assets](#assets) — Upload and download files (APKs, IPAs, etc.)
|
|
102
|
+
- [Sessions](#sessions) — Persistent connections for fast, interactive device control
|
|
103
|
+
- [Xcode Build Pipeline](#xcode-build-pipeline) — Sync code and run xcodebuild remotely
|
|
104
|
+
- [Skills](#skills) — Install Limrun skills for AI coding agents (Claude Code, Cursor, Codex)
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
### iOS
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
lim ios create # Create a new iOS instance
|
|
112
|
+
lim ios list # List all ready iOS instances
|
|
113
|
+
lim ios get <ID> # Get details of a specific instance
|
|
114
|
+
lim ios delete <ID> # Delete an instance
|
|
115
|
+
lim ios info # Get device info from a running instance
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
#### Create Options
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
# Basic
|
|
122
|
+
lim ios create
|
|
123
|
+
|
|
124
|
+
# With specific device model
|
|
125
|
+
lim ios create --model ipad --rm
|
|
126
|
+
|
|
127
|
+
# With pre-installed app from asset storage
|
|
128
|
+
lim ios create --install-asset my-app.ipa
|
|
129
|
+
|
|
130
|
+
# With Xcode sandbox enabled
|
|
131
|
+
lim ios create --xcode
|
|
132
|
+
|
|
133
|
+
# Full options
|
|
134
|
+
lim ios create --region us-west --display-name "CI Test" --label env=ci --rm
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**Flags for `ios create`:**
|
|
138
|
+
|
|
139
|
+
| Flag | Description |
|
|
140
|
+
| --------------------------------- | ------------------------------------------------------ |
|
|
141
|
+
| `--rm` | Auto-delete the instance on exit (Ctrl+C) |
|
|
142
|
+
| `--model <iphone\|ipad\|watch>` | Simulator device model |
|
|
143
|
+
| `--xcode` | Attach a Xcode build sandbox to the iOS instance |
|
|
144
|
+
| `--region <value>` | Region for the instance (e.g. `us-west`) |
|
|
145
|
+
| `--display-name <value>` | Human-readable name |
|
|
146
|
+
| `--label <key=value>` | Labels (repeatable). Used for filtering and reuse |
|
|
147
|
+
| `--hard-timeout <duration>` | Max lifetime (e.g. `1m`, `10m`, `3h`). Default: none |
|
|
148
|
+
| `--inactivity-timeout <duration>` | Idle timeout. Default: `3m` |
|
|
149
|
+
| `--reuse-if-exists` | Reuse an existing instance with matching labels/region |
|
|
150
|
+
| `--install <file>` | Local file to install (auto-uploads, repeatable) |
|
|
151
|
+
| `--install-asset <name>` | Asset name to install (repeatable) |
|
|
152
|
+
|
|
153
|
+
#### List and Filter
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
lim ios list # Ready instances
|
|
157
|
+
lim ios list --all # All states
|
|
158
|
+
lim ios list --state creating # Filter by state
|
|
159
|
+
lim ios list --region us-west # Filter by region
|
|
160
|
+
lim ios list --label-selector env=prod # Filter by labels
|
|
161
|
+
lim ios list --json # JSON output
|
|
162
|
+
lim ios get <ID> # Single instance details
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
#### Device Interaction
|
|
166
|
+
|
|
167
|
+
All interaction commands accept an optional `--id`. When omitted, the last created iOS instance is used.
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
# Device info
|
|
171
|
+
lim ios info
|
|
172
|
+
lim ios info --json
|
|
173
|
+
|
|
174
|
+
# Screenshots
|
|
175
|
+
lim ios screenshot screenshot.png
|
|
176
|
+
|
|
177
|
+
# Tapping
|
|
178
|
+
lim ios tap 100 200
|
|
179
|
+
lim ios tap-element --ax-label "Submit"
|
|
180
|
+
lim ios tap-element --ax-unique-id btn_ok
|
|
181
|
+
|
|
182
|
+
# Text input
|
|
183
|
+
lim ios type "Hello World"
|
|
184
|
+
lim ios type "search query" --enter
|
|
185
|
+
lim ios press-key enter
|
|
186
|
+
lim ios press-key a --modifier shift
|
|
187
|
+
lim ios toggle-keyboard
|
|
188
|
+
|
|
189
|
+
# Scrolling
|
|
190
|
+
lim ios scroll down --amount 500
|
|
191
|
+
|
|
192
|
+
# Batch multiple actions in one call
|
|
193
|
+
lim ios perform --action type=tap,x=100,y=200 --action 'type=typeText,text=Hello World'
|
|
194
|
+
lim ios perform --action type=wait,durationMs=500 --action type=pressKey,key=enter
|
|
195
|
+
lim ios perform --file ./actions.yaml
|
|
196
|
+
|
|
197
|
+
# actions.yaml
|
|
198
|
+
- type: tap
|
|
199
|
+
x: 100
|
|
200
|
+
y: 200
|
|
201
|
+
- type: typeText
|
|
202
|
+
text: "Hello World"
|
|
203
|
+
|
|
204
|
+
# UI inspection
|
|
205
|
+
lim ios element-tree
|
|
206
|
+
lim ios element-tree | jq '.'
|
|
207
|
+
|
|
208
|
+
# Open URLs / deep links
|
|
209
|
+
lim ios open-url https://example.com
|
|
210
|
+
lim ios open-url myapp://settings
|
|
211
|
+
|
|
212
|
+
# Low-level simulator access
|
|
213
|
+
lim ios simctl -- listapps booted
|
|
214
|
+
lim ios xcrun -- --sdk iphonesimulator --show-sdk-version
|
|
215
|
+
lim ios xcodebuild -- -version
|
|
216
|
+
lim ios cp payload.json ./fixtures/payload.json
|
|
217
|
+
lim ios lsof
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
#### App Management (iOS only)
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
# Install an app (local file auto-uploads, or use URL)
|
|
224
|
+
lim ios install-app ./MyApp.ipa
|
|
225
|
+
lim ios install-app https://example.com/app.ipa
|
|
226
|
+
lim ios install-app https://example.com/app.ipa --md5 <hex-digest>
|
|
227
|
+
lim ios install-app ./MyApp.ipa --launch-mode RelaunchIfRunning
|
|
228
|
+
|
|
229
|
+
# Launch / terminate
|
|
230
|
+
lim ios launch-app com.example.myapp
|
|
231
|
+
lim ios launch-app com.example.myapp --mode RelaunchIfRunning
|
|
232
|
+
lim ios terminate-app com.example.myapp
|
|
233
|
+
|
|
234
|
+
# List installed apps
|
|
235
|
+
lim ios list-apps
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
#### Log Streaming (iOS only)
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
# Tail recent logs
|
|
242
|
+
lim ios app-log com.example.myapp --tail 50
|
|
243
|
+
|
|
244
|
+
# Stream logs continuously (Ctrl+C to stop)
|
|
245
|
+
lim ios app-log com.example.myapp --follow
|
|
246
|
+
|
|
247
|
+
# Stream full simulator syslog
|
|
248
|
+
lim ios syslog
|
|
249
|
+
lim ios syslog --json
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
#### Video Recording
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
lim ios record start
|
|
256
|
+
lim ios record start --quality 8
|
|
257
|
+
lim ios record stop
|
|
258
|
+
lim ios record stop -o recording.mp4
|
|
259
|
+
lim ios record stop --presigned-url https://example.com/upload
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
#### Built App Sync (iOS only)
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
# Sync a built .app bundle to the current iOS instance
|
|
266
|
+
lim ios sync ./Build/Products/Debug-iphonesimulator/MyApp.app
|
|
267
|
+
|
|
268
|
+
# Re-sync on changes and relaunch if the app is already running
|
|
269
|
+
lim ios sync ./MyApp.app --watch --launch-mode RelaunchIfRunning
|
|
270
|
+
|
|
271
|
+
# Tune the delta-sync cache and patch size
|
|
272
|
+
lim ios sync ./MyApp.app --basis-cache-dir ./.limsync-cache --max-patch-bytes 2097152
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
### Android
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
lim android create # Create a new Android instance
|
|
281
|
+
lim android list # List all ready Android instances
|
|
282
|
+
lim android get <ID> # Get details of a specific instance
|
|
283
|
+
lim android delete <ID> # Delete an instance
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
#### Create Options
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
# Basic (prints a Console URL you can open in the browser)
|
|
290
|
+
lim android create
|
|
291
|
+
|
|
292
|
+
# With apps pre-installed
|
|
293
|
+
lim android create --install ./my-app.apk --install ./another.apk
|
|
294
|
+
|
|
295
|
+
# Create without opening an ADB tunnel
|
|
296
|
+
lim android create --no-connect
|
|
297
|
+
|
|
298
|
+
# Full options
|
|
299
|
+
lim android create --region us-west --display-name "CI Test" --label env=ci --rm
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
**Android-specific flags:**
|
|
303
|
+
|
|
304
|
+
| Flag | Description |
|
|
305
|
+
| ------------------- | ----------------------------------------------- |
|
|
306
|
+
| `--[no-]connect` | Start an ADB tunnel immediately (default: true) |
|
|
307
|
+
| `--adb-path <path>` | Path to `adb` binary (default: `adb`) |
|
|
308
|
+
|
|
309
|
+
`lim android create` always prints a Console URL such as `https://console.limrun.com/stream/android_...` that you can open in the browser for live viewing. For automation, `--no-connect` is usually the safest default.
|
|
310
|
+
|
|
311
|
+
#### Device Interaction
|
|
312
|
+
|
|
313
|
+
All interaction commands accept an optional `--id`. When omitted, the last created Android instance is used.
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
# Screenshots
|
|
317
|
+
lim android screenshot screenshot.png
|
|
318
|
+
|
|
319
|
+
# Tapping
|
|
320
|
+
lim android tap 100 200
|
|
321
|
+
lim android tap-element --resource-id com.example:id/button
|
|
322
|
+
lim android tap-element --content-desc "Sign In button"
|
|
323
|
+
lim android tap-element --text "Sign In"
|
|
324
|
+
lim android find-element --resource-id com.example:id/button --json
|
|
325
|
+
|
|
326
|
+
# Text input
|
|
327
|
+
lim android type "Hello World"
|
|
328
|
+
lim android type "Hello World" --resource-id com.example:id/search_input
|
|
329
|
+
lim android press-key enter
|
|
330
|
+
|
|
331
|
+
# Scrolling
|
|
332
|
+
lim android scroll down --amount 500
|
|
333
|
+
lim android scroll down --resource-id com.example:id/list --amount 500
|
|
334
|
+
|
|
335
|
+
# UI inspection
|
|
336
|
+
lim android element-tree
|
|
337
|
+
|
|
338
|
+
# Install app
|
|
339
|
+
lim android install-app ./app.apk
|
|
340
|
+
|
|
341
|
+
# Open URL
|
|
342
|
+
lim android open-url https://example.com
|
|
343
|
+
|
|
344
|
+
# Video recording
|
|
345
|
+
lim android record start
|
|
346
|
+
lim android record start --quality 8
|
|
347
|
+
lim android record stop
|
|
348
|
+
lim android record stop -o recording.mp4
|
|
349
|
+
lim android record stop --presigned-url https://example.com/upload
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
#### ADB Tunnel
|
|
353
|
+
|
|
354
|
+
Connect to a running Android instance for direct `adb` access:
|
|
355
|
+
|
|
356
|
+
```bash
|
|
357
|
+
lim android connect
|
|
358
|
+
lim android connect --id android_abc123 --adb-path /usr/local/bin/adb
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
The tunnel stays open until you press Ctrl+C. While connected, you can use `adb` commands in another terminal.
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
### Xcode
|
|
366
|
+
|
|
367
|
+
Standalone Xcode build sandboxes for remote compilation.
|
|
368
|
+
|
|
369
|
+
```bash
|
|
370
|
+
lim xcode create # Create a new Xcode sandbox
|
|
371
|
+
lim xcode create --ios # Create an iOS instance with an attached Xcode sandbox
|
|
372
|
+
lim xcode list # List all ready Xcode instances
|
|
373
|
+
lim xcode get <ID> # Get details of a specific instance
|
|
374
|
+
lim xcode delete <ID> # Delete an instance
|
|
375
|
+
lim xcode attach-simulator <IOS_ID> --id <XCODE_ID>
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
# Create with options
|
|
380
|
+
lim xcode create --rm --region us-west --hard-timeout 1h
|
|
381
|
+
|
|
382
|
+
# Build (automatically syncs the project path first)
|
|
383
|
+
lim xcode build ./MyProject --scheme MyApp --workspace MyApp.xcworkspace
|
|
384
|
+
|
|
385
|
+
# Build and upload artifact
|
|
386
|
+
lim xcode build ./MyProject --scheme MyApp --upload my-app-build
|
|
387
|
+
|
|
388
|
+
# Signed device build
|
|
389
|
+
lim xcode build ./MyProject --scheme MyApp --certificate-p12 ./certificate.p12 --certificate-password "$P12_PASSWORD" --provisioning-profile ./profile.mobileprovision --upload signed-device-build.ipa
|
|
390
|
+
|
|
391
|
+
# Attach an existing simulator so builds auto-install there
|
|
392
|
+
lim xcode attach-simulator ios_abc123 --id sandbox_def456
|
|
393
|
+
|
|
394
|
+
# Tune sync cache, patch size, or ignore additional paths
|
|
395
|
+
lim xcode sync ./MyProject --watch --basis-cache-dir ./.limsync-cache --max-patch-bytes 2097152
|
|
396
|
+
lim xcode sync ./MyProject --ignore "\\.xcuserdata/" --ignore "^DerivedData/"
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
### Assets
|
|
402
|
+
|
|
403
|
+
Assets are files (APKs, IPAs, configs, etc.) stored in Limrun's cloud storage for use with instances.
|
|
404
|
+
|
|
405
|
+
```bash
|
|
406
|
+
# Upload a file
|
|
407
|
+
lim asset push ./my-app.apk
|
|
408
|
+
lim asset push ./my-app.ipa -n custom-name
|
|
409
|
+
|
|
410
|
+
# Download a file
|
|
411
|
+
lim asset pull asset_abc123
|
|
412
|
+
lim asset pull asset_abc123 -o ./downloads
|
|
413
|
+
lim asset list --name my-app.apk --json
|
|
414
|
+
lim asset pull asset_abc123
|
|
415
|
+
|
|
416
|
+
# List assets
|
|
417
|
+
lim asset list
|
|
418
|
+
lim asset list --name my-app
|
|
419
|
+
lim asset list --name-prefix builds/
|
|
420
|
+
lim asset list --download-url
|
|
421
|
+
lim asset list --include-app-store
|
|
422
|
+
|
|
423
|
+
# Get a specific asset
|
|
424
|
+
lim asset list asset_abc123
|
|
425
|
+
|
|
426
|
+
# Delete an asset
|
|
427
|
+
lim asset delete asset_abc123
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
### Sessions
|
|
433
|
+
|
|
434
|
+
Sessions keep a persistent WebSocket connection to an instance in the background, making all interaction commands near-instant (~50ms instead of ~2s per command).
|
|
435
|
+
|
|
436
|
+
#### Why Sessions?
|
|
437
|
+
|
|
438
|
+
Without a session, every command creates a new connection:
|
|
439
|
+
|
|
440
|
+
```
|
|
441
|
+
lim ios screenshot screenshot.png # ~2s (connect + auth + screenshot + disconnect)
|
|
442
|
+
lim ios tap 100 200 # ~2s (connect + auth + tap + disconnect)
|
|
443
|
+
lim ios element-tree # ~2s (connect + auth + fetch + disconnect)
|
|
444
|
+
# Total: ~6s for 3 commands
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
With a session, the connection is created once and reused:
|
|
448
|
+
|
|
449
|
+
```
|
|
450
|
+
lim session start # ~2s (one-time connection setup)
|
|
451
|
+
lim ios screenshot screenshot.png # ~50ms (reuses connection)
|
|
452
|
+
lim ios tap 100 200 # ~50ms (reuses connection)
|
|
453
|
+
lim ios element-tree # ~50ms (reuses connection)
|
|
454
|
+
lim session stop # instant cleanup
|
|
455
|
+
# Total: ~2.15s for 3 commands
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
This makes sessions essential for interactive workflows, AI agent loops, and any scenario where you run multiple commands against the same instance.
|
|
459
|
+
|
|
460
|
+
#### Session Commands
|
|
461
|
+
|
|
462
|
+
```bash
|
|
463
|
+
# Start a session (defaults to the last remembered iOS instance, otherwise Android, then Xcode)
|
|
464
|
+
lim session start
|
|
465
|
+
|
|
466
|
+
# Or specify an instance explicitly
|
|
467
|
+
lim session start --id ios_abc123
|
|
468
|
+
|
|
469
|
+
# Multiple sessions can run simultaneously
|
|
470
|
+
lim session start --id ios_abc123
|
|
471
|
+
lim session start --id android_def456
|
|
472
|
+
|
|
473
|
+
# Check all active sessions
|
|
474
|
+
lim session status
|
|
475
|
+
lim session status --json
|
|
476
|
+
|
|
477
|
+
# Stop a specific session
|
|
478
|
+
lim session stop --id ios_abc123
|
|
479
|
+
|
|
480
|
+
# Stop all sessions at once
|
|
481
|
+
lim session stop --all
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
If only one session is active, `lim session stop` (no ID) stops it automatically. For scripts and agents, prefer `--id` explicitly so the target instance is unambiguous.
|
|
485
|
+
|
|
486
|
+
#### How It Works
|
|
487
|
+
|
|
488
|
+
Each `lim session start` spawns an independent background daemon that:
|
|
489
|
+
|
|
490
|
+
- Holds a persistent WebSocket connection to that specific instance
|
|
491
|
+
- Listens on its own Unix socket under `~/.lim/sessions/<hashed-instance-id>/`
|
|
492
|
+
- All interaction commands automatically detect the matching session and route through it
|
|
493
|
+
- Multiple sessions run in parallel with no shared state
|
|
494
|
+
|
|
495
|
+
#### Example: Interactive Testing
|
|
496
|
+
|
|
497
|
+
```bash
|
|
498
|
+
lim ios create --model iphone
|
|
499
|
+
lim session start
|
|
500
|
+
|
|
501
|
+
# Fast interaction loop — each command takes ~50ms
|
|
502
|
+
lim ios launch-app com.example.myapp
|
|
503
|
+
lim ios element-tree | jq '.tree'
|
|
504
|
+
lim ios tap-element --ax-label "Login"
|
|
505
|
+
lim ios type "user@example.com"
|
|
506
|
+
lim ios tap-element --ax-label "Submit"
|
|
507
|
+
lim ios screenshot after-login.png
|
|
508
|
+
|
|
509
|
+
lim session stop
|
|
510
|
+
lim ios delete ios_abc123
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
#### Example: Multi-Device AI Agent
|
|
514
|
+
|
|
515
|
+
```bash
|
|
516
|
+
# Create two instances and start sessions for both
|
|
517
|
+
lim ios create --model iphone
|
|
518
|
+
lim ios create --model ipad
|
|
519
|
+
lim session start --id ios_phone_123
|
|
520
|
+
lim session start --id ios_tablet_456
|
|
521
|
+
|
|
522
|
+
# Agent controls both devices in parallel — ~50ms per command
|
|
523
|
+
lim ios launch-app com.example.myapp --id ios_phone_123
|
|
524
|
+
lim ios launch-app com.example.myapp --id ios_tablet_456
|
|
525
|
+
|
|
526
|
+
lim ios screenshot phone.png --id ios_phone_123
|
|
527
|
+
lim ios screenshot tablet.png --id ios_tablet_456
|
|
528
|
+
|
|
529
|
+
lim ios tap 200 400 --id ios_phone_123
|
|
530
|
+
lim ios element-tree --id ios_tablet_456 --json > tablet-tree.json
|
|
531
|
+
|
|
532
|
+
# Clean up all sessions
|
|
533
|
+
lim session stop --all
|
|
534
|
+
lim ios delete ios_phone_123
|
|
535
|
+
lim ios delete ios_tablet_456
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
#### Example: Automated Test Matrix
|
|
539
|
+
|
|
540
|
+
```bash
|
|
541
|
+
# Spin up devices, start sessions, run tests, tear down
|
|
542
|
+
DEVICES=("iphone" "ipad")
|
|
543
|
+
IDS=()
|
|
544
|
+
|
|
545
|
+
for model in "${DEVICES[@]}"; do
|
|
546
|
+
ID=$(lim ios create --model $model --json | jq -r '.metadata.id')
|
|
547
|
+
lim session start --id $ID
|
|
548
|
+
IDS+=($ID)
|
|
549
|
+
done
|
|
550
|
+
|
|
551
|
+
# Run tests against all devices
|
|
552
|
+
for ID in "${IDS[@]}"; do
|
|
553
|
+
lim ios launch-app com.example.myapp --id $ID
|
|
554
|
+
lim ios screenshot "test_${ID}.png" --id $ID
|
|
555
|
+
done
|
|
556
|
+
|
|
557
|
+
# Tear down
|
|
558
|
+
lim session stop --all
|
|
559
|
+
for ID in "${IDS[@]}"; do
|
|
560
|
+
lim ios delete $ID
|
|
561
|
+
done
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
---
|
|
565
|
+
|
|
566
|
+
### Xcode Build Pipeline
|
|
567
|
+
|
|
568
|
+
Build and test iOS apps remotely using cloud Xcode sandboxes. The `sync` and `build` commands work with both standalone Xcode instances and iOS instances that have Xcode sandbox enabled.
|
|
569
|
+
|
|
570
|
+
#### Option A: iOS Instance with Xcode Sandbox (Recommended)
|
|
571
|
+
|
|
572
|
+
This gives you a simulator **and** a build environment in one instance — the built app is automatically installed on the simulator.
|
|
573
|
+
|
|
574
|
+
```bash
|
|
575
|
+
# 1. Create iOS instance with Xcode sandbox
|
|
576
|
+
lim ios create --xcode
|
|
577
|
+
# Output:
|
|
578
|
+
# Instance ID: ios_abc123
|
|
579
|
+
# Xcode Sandbox: https://...limrun.net/v1/sandbox_.../xcode
|
|
580
|
+
# (sandbox URL is cached locally for sync/build to use)
|
|
581
|
+
|
|
582
|
+
# 2. Build — automatically syncs your project code first, then auto-installs on the simulator
|
|
583
|
+
lim xcode build ./MyProject --id ios_abc123 --scheme MyApp --workspace MyApp.xcworkspace
|
|
584
|
+
|
|
585
|
+
# 3. Start a session for fast device interaction
|
|
586
|
+
lim session start
|
|
587
|
+
|
|
588
|
+
# 4. Test the built app on the simulator (~50ms per command)
|
|
589
|
+
lim ios launch-app com.example.myapp
|
|
590
|
+
lim ios element-tree | jq '.'
|
|
591
|
+
lim ios screenshot built-app.png
|
|
592
|
+
|
|
593
|
+
# 5. Clean up
|
|
594
|
+
lim session stop
|
|
595
|
+
lim ios delete ios_abc123
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
> **Note:** `lim xcode build` already syncs the project path you pass before invoking `xcodebuild`, so you do not need to call `lim xcode sync` first. The Xcode sandbox URL is only returned when the instance is created — not on subsequent `list` calls. The CLI caches it locally at `~/.lim/instances/` so that build workflows can find it. This means `build` must run on the same machine where `ios create --xcode` was executed.
|
|
599
|
+
|
|
600
|
+
#### Option B: Standalone Xcode Instance
|
|
601
|
+
|
|
602
|
+
Use this when you only need to build (no simulator needed), or when you want to attach a simulator separately.
|
|
603
|
+
|
|
604
|
+
```bash
|
|
605
|
+
# 1. Create a standalone Xcode instance
|
|
606
|
+
lim xcode create --rm
|
|
607
|
+
|
|
608
|
+
# 2. Optionally attach an existing simulator by ID
|
|
609
|
+
lim xcode attach-simulator ios_abc123 --id sandbox_def456
|
|
610
|
+
|
|
611
|
+
# 3. Build (automatically syncs the project path first)
|
|
612
|
+
lim xcode build ./MyProject --scheme MyApp --workspace MyApp.xcworkspace
|
|
613
|
+
|
|
614
|
+
# 4. Upload build artifact
|
|
615
|
+
lim xcode build ./MyProject --scheme MyApp --upload my-app-build
|
|
616
|
+
|
|
617
|
+
# Signed device builds default to --sdk iphoneos when signing assets are provided
|
|
618
|
+
lim xcode build ./MyProject --scheme MyApp --certificate-p12 ./certificate.p12 --certificate-password "$P12_PASSWORD" --provisioning-profile ./profile.mobileprovision --upload signed-device-build.ipa
|
|
619
|
+
|
|
620
|
+
# 5. Download the artifact
|
|
621
|
+
lim asset pull my-app-build -o ./build-output
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
#### Build Behavior
|
|
625
|
+
|
|
626
|
+
`lim xcode build [PATH]` automatically performs a one-shot code sync for the given project path before invoking `xcodebuild`. The sync step automatically ignores build artifacts (`build/`, `DerivedData/`, `.build/`), dependency folders (`Pods/`, `Carthage/Build/`, `.swiftpm/`), and user-specific files (`xcuserdata/`, `.dSYM/`).
|
|
627
|
+
|
|
628
|
+
Provide `--certificate-p12`, `--certificate-password`, and `--provisioning-profile` together to sign a real-device build. When signing assets are provided without `--sdk`, the CLI builds with `iphoneos`; pass `--sdk watchos` for signed watchOS device builds.
|
|
629
|
+
|
|
630
|
+
---
|
|
631
|
+
|
|
632
|
+
### Skills
|
|
633
|
+
|
|
634
|
+
Fetch the latest Limrun skills from `limrun-inc/skills@main` and install them into the native skills directory of AI coding agents (Claude Code, Cursor, Codex). After installation, the agent auto-discovers the skill and triggers it when you ask things like "build the iOS app" or "show me a screenshot."
|
|
635
|
+
|
|
636
|
+
```bash
|
|
637
|
+
# Interactive: prompts for agents (with detected ones pre-checked) and scope
|
|
638
|
+
lim skills install
|
|
639
|
+
|
|
640
|
+
# Non-interactive
|
|
641
|
+
lim skills install --agents claude --scope project
|
|
642
|
+
lim skills install --agents claude --agents cursor --scope project
|
|
643
|
+
lim skills install --agents codex --scope global
|
|
644
|
+
lim skills install --agents cursor --scope project --skills limrun-expo-development
|
|
645
|
+
|
|
646
|
+
# Overwrite existing skill directories (otherwise the command refuses on non-interactive runs)
|
|
647
|
+
lim skills install --agents claude --scope project --force
|
|
648
|
+
|
|
649
|
+
# Machine-readable output for scripts
|
|
650
|
+
lim skills install --agents claude --scope project --json
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
**Flags:**
|
|
654
|
+
|
|
655
|
+
| Flag | Description |
|
|
656
|
+
| --------------------------- | -------------------------------------------------------------------------------------------- |
|
|
657
|
+
| `--agents <id>` | Target agent. Repeat to select multiple. One of: `claude`, `cursor`, `codex`. |
|
|
658
|
+
| `--skills <name>` | Limrun skill to install. Repeat to select multiple. Defaults to the remote catalog default. |
|
|
659
|
+
| `--scope <project\|global>` | `project` writes into the current directory; `global` writes into the user's home directory. |
|
|
660
|
+
| `--force` | Overwrite existing skill directories without confirmation. |
|
|
661
|
+
| `--json` | Emit structured JSON instead of the human summary. |
|
|
662
|
+
| `--quiet` | Suppress non-result output. |
|
|
663
|
+
|
|
664
|
+
**Available skills:**
|
|
665
|
+
|
|
666
|
+
- `limrun-xcode-and-ios-simulator` (default): Build, launch, and control iOS apps with remote XCode and Simulators.
|
|
667
|
+
- `limrun-expo-development`: Iterate on Expo / React Native apps with remote iOS dev-client workflows.
|
|
668
|
+
- `limrun-detox-testing`: Configure, run, and debug Detox against Limrun iOS simulators.
|
|
669
|
+
|
|
670
|
+
**Install paths:**
|
|
671
|
+
|
|
672
|
+
| Agent | Project | Global |
|
|
673
|
+
| ----------- | ------------------------- | -------------------------------------------------------------------------- |
|
|
674
|
+
| Claude Code | `.claude/skills/<skill>/` | `$CLAUDE_CONFIG_DIR/skills/<skill>/` (default `~/.claude/skills/<skill>/`) |
|
|
675
|
+
| Cursor | `.agents/skills/<skill>/` | `~/.agents/skills/<skill>/` |
|
|
676
|
+
| Codex | `.codex/skills/<skill>/` | `$CODEX_HOME/skills/<skill>/` (default `~/.codex/skills/<skill>/`) |
|
|
677
|
+
|
|
678
|
+
**Behavior:**
|
|
679
|
+
|
|
680
|
+
- The command fetches `limrun-inc/skills@main` at runtime, so skill updates do not require a new `lim` release.
|
|
681
|
+
- The command compares fetched vs existing skill directories byte-for-byte. Identical content is reported as `Unchanged` (no writes).
|
|
682
|
+
- Different content: in interactive mode you are asked to confirm each overwrite; in non-interactive mode the command refuses unless `--force` is passed.
|
|
683
|
+
- Non-interactive runs are all-or-nothing: if any selected target conflicts and `--force` is not set, no files are written for any target, and the command exits with status 1.
|
|
684
|
+
- Ctrl-C cancellation at any prompt exits cleanly without writing.
|
|
685
|
+
|
|
686
|
+
Cursor reads `.agents/skills/` natively, so we install there rather than `.cursor/skills/`. As a bonus, the same install reaches OpenCode and any other tool that follows the AGENTS.md convention - no extra menu options needed.
|
|
687
|
+
|
|
688
|
+
---
|
|
689
|
+
|
|
690
|
+
## Configuration
|
|
691
|
+
|
|
692
|
+
The CLI reads configuration from multiple sources (in order of precedence):
|
|
693
|
+
|
|
694
|
+
1. Command-line flags (`--api-key`)
|
|
695
|
+
2. Environment variables (`LIM_API_KEY`, `LIM_API_ENDPOINT`, `LIM_CONSOLE_ENDPOINT`), including values loaded from a local `.env` file
|
|
696
|
+
3. Config file (`~/.lim/config.yaml`)
|
|
697
|
+
|
|
698
|
+
**Config file keys:**
|
|
699
|
+
|
|
700
|
+
| Key | Default | Description |
|
|
701
|
+
| ------------------ | ---------------------------- | ----------------------- |
|
|
702
|
+
| `api-key` | — | Your Limrun API key |
|
|
703
|
+
| `api-endpoint` | `https://api.limrun.com` | API base URL |
|
|
704
|
+
| `console-endpoint` | `https://console.limrun.com` | Console URL (for login) |
|
|
705
|
+
|
|
706
|
+
---
|
|
707
|
+
|
|
708
|
+
## JSON Output
|
|
709
|
+
|
|
710
|
+
All commands support `--json` for machine-readable output, making the CLI suitable for scripting and AI agent automation:
|
|
711
|
+
|
|
712
|
+
```bash
|
|
713
|
+
# Get instance details as JSON
|
|
714
|
+
lim ios get ios_abc123 --json
|
|
715
|
+
|
|
716
|
+
# Parse with jq
|
|
717
|
+
lim android list --json | jq '.[].metadata.id'
|
|
718
|
+
|
|
719
|
+
# Use in scripts
|
|
720
|
+
INSTANCE_ID=$(lim ios create --json | jq -r '.metadata.id')
|
|
721
|
+
lim ios screenshot test.png --id $INSTANCE_ID
|
|
722
|
+
lim ios delete $INSTANCE_ID
|
|
723
|
+
```
|
|
724
|
+
|
|
725
|
+
---
|
|
726
|
+
|
|
727
|
+
## Workflows
|
|
728
|
+
|
|
729
|
+
### CI Testing: Install and Verify an App
|
|
730
|
+
|
|
731
|
+
```bash
|
|
732
|
+
# Create instance and start session for fast commands
|
|
733
|
+
lim ios create --install ./build/MyApp.ipa
|
|
734
|
+
lim session start
|
|
735
|
+
|
|
736
|
+
# Verify — each command takes ~50ms with session
|
|
737
|
+
lim ios launch-app com.example.myapp
|
|
738
|
+
sleep 2
|
|
739
|
+
lim ios element-tree | grep "Welcome"
|
|
740
|
+
lim ios screenshot test-result.png
|
|
741
|
+
|
|
742
|
+
# Clean up
|
|
743
|
+
lim session stop
|
|
744
|
+
lim ios delete ios_abc123
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
### AI Agent Automation
|
|
748
|
+
|
|
749
|
+
```bash
|
|
750
|
+
# Create instance
|
|
751
|
+
INSTANCE=$(lim ios create --model iphone --json)
|
|
752
|
+
ID=$(echo $INSTANCE | jq -r '.metadata.id')
|
|
753
|
+
|
|
754
|
+
# Start session — all commands now run in ~50ms
|
|
755
|
+
lim session start
|
|
756
|
+
|
|
757
|
+
# Agent can interact at high speed
|
|
758
|
+
lim ios tap 200 400
|
|
759
|
+
lim ios type "test@example.com"
|
|
760
|
+
lim ios tap-element --ax-label "Sign In"
|
|
761
|
+
lim ios screenshot result.png
|
|
762
|
+
lim ios element-tree --json > ui-state.json
|
|
763
|
+
|
|
764
|
+
# Tail logs (non-streaming works through session too)
|
|
765
|
+
lim ios app-log com.example.myapp --tail 20
|
|
766
|
+
|
|
767
|
+
# Clean up
|
|
768
|
+
lim session stop
|
|
769
|
+
lim ios delete $ID
|
|
770
|
+
```
|
|
771
|
+
|
|
772
|
+
### Remote Build + Test on iOS Simulator
|
|
773
|
+
|
|
774
|
+
```bash
|
|
775
|
+
# Single instance: Xcode sandbox + iOS simulator
|
|
776
|
+
ID=$(lim ios create --xcode --json | jq -r '.metadata.id')
|
|
777
|
+
|
|
778
|
+
# Build and test (build automatically syncs the project path first)
|
|
779
|
+
lim xcode build ./MyiOSProject --id $ID --scheme MyApp --workspace MyApp.xcworkspace
|
|
780
|
+
|
|
781
|
+
# Verify the built app on the simulator
|
|
782
|
+
lim session start
|
|
783
|
+
lim ios launch-app com.example.myapp
|
|
784
|
+
sleep 2
|
|
785
|
+
lim ios element-tree | grep "Welcome"
|
|
786
|
+
lim ios screenshot test-result.png
|
|
787
|
+
lim session stop
|
|
788
|
+
|
|
789
|
+
lim ios delete $ID
|
|
790
|
+
```
|
|
791
|
+
|
|
792
|
+
### Build-Only with Artifact Upload
|
|
793
|
+
|
|
794
|
+
```bash
|
|
795
|
+
lim xcode create --rm --reuse-if-exists --label project=myapp
|
|
796
|
+
|
|
797
|
+
lim xcode build ./MyiOSProject --scheme MyApp --workspace MyApp.xcworkspace --upload myapp-latest
|
|
798
|
+
lim asset list --name myapp-latest --json
|
|
799
|
+
lim asset pull asset_abc123 -o ./build-output
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
---
|
|
803
|
+
|
|
804
|
+
## Development
|
|
805
|
+
|
|
806
|
+
### Setup
|
|
807
|
+
|
|
808
|
+
```bash
|
|
809
|
+
cd packages/cli
|
|
810
|
+
npm install
|
|
811
|
+
npm run build
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
### Run commands during development
|
|
815
|
+
|
|
816
|
+
```bash
|
|
817
|
+
# After making changes, rebuild and run
|
|
818
|
+
npm run build && node bin/run.js <command>
|
|
819
|
+
|
|
820
|
+
# Or use watch mode in one terminal, run in another
|
|
821
|
+
npx tsc --watch # Terminal 1
|
|
822
|
+
node bin/run.js ios list # Terminal 2
|
|
823
|
+
```
|
|
824
|
+
|
|
825
|
+
### Link globally
|
|
826
|
+
|
|
827
|
+
```bash
|
|
828
|
+
npm link
|
|
829
|
+
|
|
830
|
+
# Now `lim` works anywhere on your machine
|
|
831
|
+
lim --help
|
|
832
|
+
lim android list
|
|
833
|
+
|
|
834
|
+
# Unlink when done
|
|
835
|
+
npm unlink -g lim
|
|
836
|
+
```
|