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.
Files changed (333) hide show
  1. package/README.md +836 -0
  2. package/bin/dev.js +16 -0
  3. package/bin/run.js +63 -0
  4. package/dist/base-command.d.ts +51 -0
  5. package/dist/base-command.d.ts.map +1 -0
  6. package/dist/base-command.js +441 -0
  7. package/dist/base-command.js.map +1 -0
  8. package/dist/commands/android/connect.d.ts +17 -0
  9. package/dist/commands/android/connect.d.ts.map +1 -0
  10. package/dist/commands/android/connect.js +50 -0
  11. package/dist/commands/android/connect.js.map +1 -0
  12. package/dist/commands/android/create.d.ts +25 -0
  13. package/dist/commands/android/create.d.ts.map +1 -0
  14. package/dist/commands/android/create.js +202 -0
  15. package/dist/commands/android/create.js.map +1 -0
  16. package/dist/commands/android/delete.d.ts +17 -0
  17. package/dist/commands/android/delete.d.ts.map +1 -0
  18. package/dist/commands/android/delete.js +44 -0
  19. package/dist/commands/android/delete.js.map +1 -0
  20. package/dist/commands/android/element-tree.d.ts +16 -0
  21. package/dist/commands/android/element-tree.d.ts.map +1 -0
  22. package/dist/commands/android/element-tree.js +60 -0
  23. package/dist/commands/android/element-tree.js.map +1 -0
  24. package/dist/commands/android/find-element.d.ts +28 -0
  25. package/dist/commands/android/find-element.d.ts.map +1 -0
  26. package/dist/commands/android/find-element.js +70 -0
  27. package/dist/commands/android/find-element.js.map +1 -0
  28. package/dist/commands/android/get.d.ts +17 -0
  29. package/dist/commands/android/get.d.ts.map +1 -0
  30. package/dist/commands/android/get.js +43 -0
  31. package/dist/commands/android/get.js.map +1 -0
  32. package/dist/commands/android/install-app.d.ts +18 -0
  33. package/dist/commands/android/install-app.d.ts.map +1 -0
  34. package/dist/commands/android/install-app.js +70 -0
  35. package/dist/commands/android/install-app.js.map +1 -0
  36. package/dist/commands/android/list.d.ts +19 -0
  37. package/dist/commands/android/list.d.ts.map +1 -0
  38. package/dist/commands/android/list.js +61 -0
  39. package/dist/commands/android/list.js.map +1 -0
  40. package/dist/commands/android/open-url.d.ts +18 -0
  41. package/dist/commands/android/open-url.d.ts.map +1 -0
  42. package/dist/commands/android/open-url.js +51 -0
  43. package/dist/commands/android/open-url.js.map +1 -0
  44. package/dist/commands/android/press-key.d.ts +19 -0
  45. package/dist/commands/android/press-key.d.ts.map +1 -0
  46. package/dist/commands/android/press-key.js +52 -0
  47. package/dist/commands/android/press-key.js.map +1 -0
  48. package/dist/commands/android/record.d.ts +22 -0
  49. package/dist/commands/android/record.d.ts.map +1 -0
  50. package/dist/commands/android/record.js +100 -0
  51. package/dist/commands/android/record.js.map +1 -0
  52. package/dist/commands/android/screenshot.d.ts +18 -0
  53. package/dist/commands/android/screenshot.d.ts.map +1 -0
  54. package/dist/commands/android/screenshot.js +66 -0
  55. package/dist/commands/android/screenshot.js.map +1 -0
  56. package/dist/commands/android/scroll.d.ts +32 -0
  57. package/dist/commands/android/scroll.d.ts.map +1 -0
  58. package/dist/commands/android/scroll.js +72 -0
  59. package/dist/commands/android/scroll.js.map +1 -0
  60. package/dist/commands/android/tap-element.d.ts +27 -0
  61. package/dist/commands/android/tap-element.d.ts.map +1 -0
  62. package/dist/commands/android/tap-element.js +60 -0
  63. package/dist/commands/android/tap-element.js.map +1 -0
  64. package/dist/commands/android/tap.d.ts +25 -0
  65. package/dist/commands/android/tap.d.ts.map +1 -0
  66. package/dist/commands/android/tap.js +55 -0
  67. package/dist/commands/android/tap.js.map +1 -0
  68. package/dist/commands/android/type.d.ts +31 -0
  69. package/dist/commands/android/type.d.ts.map +1 -0
  70. package/dist/commands/android/type.js +53 -0
  71. package/dist/commands/android/type.js.map +1 -0
  72. package/dist/commands/asset/delete.d.ts +17 -0
  73. package/dist/commands/asset/delete.d.ts.map +1 -0
  74. package/dist/commands/asset/delete.js +23 -0
  75. package/dist/commands/asset/delete.js.map +1 -0
  76. package/dist/commands/asset/list.d.ts +22 -0
  77. package/dist/commands/asset/list.d.ts.map +1 -0
  78. package/dist/commands/asset/list.js +97 -0
  79. package/dist/commands/asset/list.js.map +1 -0
  80. package/dist/commands/asset/pull.d.ts +19 -0
  81. package/dist/commands/asset/pull.d.ts.map +1 -0
  82. package/dist/commands/asset/pull.js +84 -0
  83. package/dist/commands/asset/pull.js.map +1 -0
  84. package/dist/commands/asset/push.d.ts +18 -0
  85. package/dist/commands/asset/push.d.ts.map +1 -0
  86. package/dist/commands/asset/push.js +43 -0
  87. package/dist/commands/asset/push.js.map +1 -0
  88. package/dist/commands/ios/app-log.d.ts +20 -0
  89. package/dist/commands/ios/app-log.d.ts.map +1 -0
  90. package/dist/commands/ios/app-log.js +86 -0
  91. package/dist/commands/ios/app-log.js.map +1 -0
  92. package/dist/commands/ios/cp.d.ts +19 -0
  93. package/dist/commands/ios/cp.d.ts.map +1 -0
  94. package/dist/commands/ios/cp.js +64 -0
  95. package/dist/commands/ios/cp.js.map +1 -0
  96. package/dist/commands/ios/create.d.ts +25 -0
  97. package/dist/commands/ios/create.d.ts.map +1 -0
  98. package/dist/commands/ios/create.js +165 -0
  99. package/dist/commands/ios/create.js.map +1 -0
  100. package/dist/commands/ios/delete.d.ts +17 -0
  101. package/dist/commands/ios/delete.d.ts.map +1 -0
  102. package/dist/commands/ios/delete.js +44 -0
  103. package/dist/commands/ios/delete.js.map +1 -0
  104. package/dist/commands/ios/element-tree.d.ts +16 -0
  105. package/dist/commands/ios/element-tree.d.ts.map +1 -0
  106. package/dist/commands/ios/element-tree.js +57 -0
  107. package/dist/commands/ios/element-tree.js.map +1 -0
  108. package/dist/commands/ios/get.d.ts +17 -0
  109. package/dist/commands/ios/get.d.ts.map +1 -0
  110. package/dist/commands/ios/get.js +44 -0
  111. package/dist/commands/ios/get.js.map +1 -0
  112. package/dist/commands/ios/info.d.ts +16 -0
  113. package/dist/commands/ios/info.d.ts.map +1 -0
  114. package/dist/commands/ios/info.js +55 -0
  115. package/dist/commands/ios/info.js.map +1 -0
  116. package/dist/commands/ios/install-app.d.ts +20 -0
  117. package/dist/commands/ios/install-app.d.ts.map +1 -0
  118. package/dist/commands/ios/install-app.js +97 -0
  119. package/dist/commands/ios/install-app.js.map +1 -0
  120. package/dist/commands/ios/launch-app.d.ts +23 -0
  121. package/dist/commands/ios/launch-app.d.ts.map +1 -0
  122. package/dist/commands/ios/launch-app.js +74 -0
  123. package/dist/commands/ios/launch-app.js.map +1 -0
  124. package/dist/commands/ios/list-apps.d.ts +16 -0
  125. package/dist/commands/ios/list-apps.d.ts.map +1 -0
  126. package/dist/commands/ios/list-apps.js +51 -0
  127. package/dist/commands/ios/list-apps.js.map +1 -0
  128. package/dist/commands/ios/list.d.ts +19 -0
  129. package/dist/commands/ios/list.d.ts.map +1 -0
  130. package/dist/commands/ios/list.js +61 -0
  131. package/dist/commands/ios/list.js.map +1 -0
  132. package/dist/commands/ios/lsof.d.ts +16 -0
  133. package/dist/commands/ios/lsof.d.ts.map +1 -0
  134. package/dist/commands/ios/lsof.js +47 -0
  135. package/dist/commands/ios/lsof.js.map +1 -0
  136. package/dist/commands/ios/open-url.d.ts +18 -0
  137. package/dist/commands/ios/open-url.d.ts.map +1 -0
  138. package/dist/commands/ios/open-url.js +51 -0
  139. package/dist/commands/ios/open-url.js.map +1 -0
  140. package/dist/commands/ios/perform.d.ts +18 -0
  141. package/dist/commands/ios/perform.d.ts.map +1 -0
  142. package/dist/commands/ios/perform.js +228 -0
  143. package/dist/commands/ios/perform.js.map +1 -0
  144. package/dist/commands/ios/press-key.d.ts +19 -0
  145. package/dist/commands/ios/press-key.d.ts.map +1 -0
  146. package/dist/commands/ios/press-key.js +52 -0
  147. package/dist/commands/ios/press-key.js.map +1 -0
  148. package/dist/commands/ios/record.d.ts +22 -0
  149. package/dist/commands/ios/record.d.ts.map +1 -0
  150. package/dist/commands/ios/record.js +101 -0
  151. package/dist/commands/ios/record.js.map +1 -0
  152. package/dist/commands/ios/reverse.d.ts +19 -0
  153. package/dist/commands/ios/reverse.d.ts.map +1 -0
  154. package/dist/commands/ios/reverse.js +97 -0
  155. package/dist/commands/ios/reverse.js.map +1 -0
  156. package/dist/commands/ios/screenshot.d.ts +18 -0
  157. package/dist/commands/ios/screenshot.d.ts.map +1 -0
  158. package/dist/commands/ios/screenshot.js +65 -0
  159. package/dist/commands/ios/screenshot.js.map +1 -0
  160. package/dist/commands/ios/scroll.d.ts +19 -0
  161. package/dist/commands/ios/scroll.d.ts.map +1 -0
  162. package/dist/commands/ios/scroll.js +57 -0
  163. package/dist/commands/ios/scroll.js.map +1 -0
  164. package/dist/commands/ios/simctl.d.ts +17 -0
  165. package/dist/commands/ios/simctl.d.ts.map +1 -0
  166. package/dist/commands/ios/simctl.js +72 -0
  167. package/dist/commands/ios/simctl.js.map +1 -0
  168. package/dist/commands/ios/sync.d.ts +23 -0
  169. package/dist/commands/ios/sync.d.ts.map +1 -0
  170. package/dist/commands/ios/sync.js +90 -0
  171. package/dist/commands/ios/sync.js.map +1 -0
  172. package/dist/commands/ios/syslog.d.ts +16 -0
  173. package/dist/commands/ios/syslog.d.ts.map +1 -0
  174. package/dist/commands/ios/syslog.js +62 -0
  175. package/dist/commands/ios/syslog.js.map +1 -0
  176. package/dist/commands/ios/tap-element.d.ts +23 -0
  177. package/dist/commands/ios/tap-element.d.ts.map +1 -0
  178. package/dist/commands/ios/tap-element.js +92 -0
  179. package/dist/commands/ios/tap-element.js.map +1 -0
  180. package/dist/commands/ios/tap.d.ts +25 -0
  181. package/dist/commands/ios/tap.d.ts.map +1 -0
  182. package/dist/commands/ios/tap.js +55 -0
  183. package/dist/commands/ios/tap.js.map +1 -0
  184. package/dist/commands/ios/terminate-app.d.ts +18 -0
  185. package/dist/commands/ios/terminate-app.d.ts.map +1 -0
  186. package/dist/commands/ios/terminate-app.js +49 -0
  187. package/dist/commands/ios/terminate-app.js.map +1 -0
  188. package/dist/commands/ios/toggle-keyboard.d.ts +15 -0
  189. package/dist/commands/ios/toggle-keyboard.d.ts.map +1 -0
  190. package/dist/commands/ios/toggle-keyboard.js +45 -0
  191. package/dist/commands/ios/toggle-keyboard.js.map +1 -0
  192. package/dist/commands/ios/type.d.ts +19 -0
  193. package/dist/commands/ios/type.d.ts.map +1 -0
  194. package/dist/commands/ios/type.js +53 -0
  195. package/dist/commands/ios/type.js.map +1 -0
  196. package/dist/commands/ios/xcodebuild.d.ts +17 -0
  197. package/dist/commands/ios/xcodebuild.d.ts.map +1 -0
  198. package/dist/commands/ios/xcodebuild.js +59 -0
  199. package/dist/commands/ios/xcodebuild.js.map +1 -0
  200. package/dist/commands/ios/xcrun.d.ts +17 -0
  201. package/dist/commands/ios/xcrun.d.ts.map +1 -0
  202. package/dist/commands/ios/xcrun.js +60 -0
  203. package/dist/commands/ios/xcrun.js.map +1 -0
  204. package/dist/commands/login.d.ts +14 -0
  205. package/dist/commands/login.d.ts.map +1 -0
  206. package/dist/commands/login.js +22 -0
  207. package/dist/commands/login.js.map +1 -0
  208. package/dist/commands/logout.d.ts +14 -0
  209. package/dist/commands/logout.d.ts.map +1 -0
  210. package/dist/commands/logout.js +18 -0
  211. package/dist/commands/logout.js.map +1 -0
  212. package/dist/commands/session/start.d.ts +16 -0
  213. package/dist/commands/session/start.d.ts.map +1 -0
  214. package/dist/commands/session/start.js +129 -0
  215. package/dist/commands/session/start.js.map +1 -0
  216. package/dist/commands/session/status.d.ts +14 -0
  217. package/dist/commands/session/status.d.ts.map +1 -0
  218. package/dist/commands/session/status.js +65 -0
  219. package/dist/commands/session/status.js.map +1 -0
  220. package/dist/commands/session/stop.d.ts +18 -0
  221. package/dist/commands/session/stop.d.ts.map +1 -0
  222. package/dist/commands/session/stop.js +76 -0
  223. package/dist/commands/session/stop.js.map +1 -0
  224. package/dist/commands/skills/install.d.ts +18 -0
  225. package/dist/commands/skills/install.d.ts.map +1 -0
  226. package/dist/commands/skills/install.js +473 -0
  227. package/dist/commands/skills/install.js.map +1 -0
  228. package/dist/commands/xcode/attach-simulator.d.ts +18 -0
  229. package/dist/commands/xcode/attach-simulator.d.ts.map +1 -0
  230. package/dist/commands/xcode/attach-simulator.js +55 -0
  231. package/dist/commands/xcode/attach-simulator.js.map +1 -0
  232. package/dist/commands/xcode/build.d.ts +35 -0
  233. package/dist/commands/xcode/build.d.ts.map +1 -0
  234. package/dist/commands/xcode/build.js +192 -0
  235. package/dist/commands/xcode/build.js.map +1 -0
  236. package/dist/commands/xcode/create.d.ts +22 -0
  237. package/dist/commands/xcode/create.d.ts.map +1 -0
  238. package/dist/commands/xcode/create.js +189 -0
  239. package/dist/commands/xcode/create.js.map +1 -0
  240. package/dist/commands/xcode/delete.d.ts +17 -0
  241. package/dist/commands/xcode/delete.d.ts.map +1 -0
  242. package/dist/commands/xcode/delete.js +44 -0
  243. package/dist/commands/xcode/delete.js.map +1 -0
  244. package/dist/commands/xcode/get.d.ts +17 -0
  245. package/dist/commands/xcode/get.d.ts.map +1 -0
  246. package/dist/commands/xcode/get.js +59 -0
  247. package/dist/commands/xcode/get.js.map +1 -0
  248. package/dist/commands/xcode/list.d.ts +18 -0
  249. package/dist/commands/xcode/list.d.ts.map +1 -0
  250. package/dist/commands/xcode/list.js +58 -0
  251. package/dist/commands/xcode/list.js.map +1 -0
  252. package/dist/commands/xcode/sync.d.ts +24 -0
  253. package/dist/commands/xcode/sync.d.ts.map +1 -0
  254. package/dist/commands/xcode/sync.js +93 -0
  255. package/dist/commands/xcode/sync.js.map +1 -0
  256. package/dist/index.d.ts +2 -0
  257. package/dist/index.d.ts.map +1 -0
  258. package/dist/index.js +6 -0
  259. package/dist/index.js.map +1 -0
  260. package/dist/lib/additional-files.d.ts +6 -0
  261. package/dist/lib/additional-files.d.ts.map +1 -0
  262. package/dist/lib/additional-files.js +19 -0
  263. package/dist/lib/additional-files.js.map +1 -0
  264. package/dist/lib/android-selector.d.ts +50 -0
  265. package/dist/lib/android-selector.d.ts.map +1 -0
  266. package/dist/lib/android-selector.js +103 -0
  267. package/dist/lib/android-selector.js.map +1 -0
  268. package/dist/lib/auth.d.ts +2 -0
  269. package/dist/lib/auth.d.ts.map +1 -0
  270. package/dist/lib/auth.js +60 -0
  271. package/dist/lib/auth.js.map +1 -0
  272. package/dist/lib/config.d.ts +65 -0
  273. package/dist/lib/config.d.ts.map +1 -0
  274. package/dist/lib/config.js +290 -0
  275. package/dist/lib/config.js.map +1 -0
  276. package/dist/lib/daemon-client.d.ts +9 -0
  277. package/dist/lib/daemon-client.d.ts.map +1 -0
  278. package/dist/lib/daemon-client.js +81 -0
  279. package/dist/lib/daemon-client.js.map +1 -0
  280. package/dist/lib/daemon.d.ts +41 -0
  281. package/dist/lib/daemon.d.ts.map +1 -0
  282. package/dist/lib/daemon.js +511 -0
  283. package/dist/lib/daemon.js.map +1 -0
  284. package/dist/lib/detox-version.d.ts +12 -0
  285. package/dist/lib/detox-version.d.ts.map +1 -0
  286. package/dist/lib/detox-version.js +30 -0
  287. package/dist/lib/detox-version.js.map +1 -0
  288. package/dist/lib/duration.d.ts +2 -0
  289. package/dist/lib/duration.d.ts.map +1 -0
  290. package/dist/lib/duration.js +37 -0
  291. package/dist/lib/duration.js.map +1 -0
  292. package/dist/lib/formatting.d.ts +3 -0
  293. package/dist/lib/formatting.d.ts.map +1 -0
  294. package/dist/lib/formatting.js +31 -0
  295. package/dist/lib/formatting.js.map +1 -0
  296. package/dist/lib/ignore-patterns.d.ts +2 -0
  297. package/dist/lib/ignore-patterns.d.ts.map +1 -0
  298. package/dist/lib/ignore-patterns.js +18 -0
  299. package/dist/lib/ignore-patterns.js.map +1 -0
  300. package/dist/lib/instance-client-factory.d.ts +29 -0
  301. package/dist/lib/instance-client-factory.d.ts.map +1 -0
  302. package/dist/lib/instance-client-factory.js +87 -0
  303. package/dist/lib/instance-client-factory.js.map +1 -0
  304. package/dist/lib/launch-app-runtime.d.ts +23 -0
  305. package/dist/lib/launch-app-runtime.d.ts.map +1 -0
  306. package/dist/lib/launch-app-runtime.js +58 -0
  307. package/dist/lib/launch-app-runtime.js.map +1 -0
  308. package/dist/lib/remote-skills.d.ts +47 -0
  309. package/dist/lib/remote-skills.d.ts.map +1 -0
  310. package/dist/lib/remote-skills.js +241 -0
  311. package/dist/lib/remote-skills.js.map +1 -0
  312. package/dist/lib/reverse-port-mapping.d.ts +6 -0
  313. package/dist/lib/reverse-port-mapping.d.ts.map +1 -0
  314. package/dist/lib/reverse-port-mapping.js +24 -0
  315. package/dist/lib/reverse-port-mapping.js.map +1 -0
  316. package/dist/lib/skills.d.ts +17 -0
  317. package/dist/lib/skills.d.ts.map +1 -0
  318. package/dist/lib/skills.js +153 -0
  319. package/dist/lib/skills.js.map +1 -0
  320. package/package.json +69 -13
  321. package/.npmignore +0 -2
  322. package/build/lib/index.js +0 -1498
  323. package/build/lib/index.map +0 -1
  324. package/build/lib/utils/courier.js +0 -98
  325. package/build/lib/utils/courier.map +0 -1
  326. package/build/lib/utils/polyfill.js +0 -53
  327. package/build/lib/utils/polyfill.map +0 -1
  328. package/build.sh +0 -9
  329. package/index.js +0 -2
  330. package/lib/index.js +0 -284
  331. package/lib/utils/courier.js +0 -108
  332. package/lib/utils/polyfill.js +0 -42
  333. 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
+ ```