@tai2/aco 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Taiju Muto
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,203 @@
1
+ # aco -- Appium Command-line Operator
2
+
3
+ [![ci](https://github.com/tai2/aco/actions/workflows/ci.yml/badge.svg)](https://github.com/tai2/aco/actions/workflows/ci.yml)
4
+ ![npm](https://img.shields.io/npm/v/@tai2/aco)
5
+
6
+ Drive an Appium session from the shell. Start a session against an app, then
7
+ send each Appium command as a single shell invocation -- no client-script
8
+ scaffolding required.
9
+
10
+ ## Prerequisites
11
+
12
+ Install Appium and at least one driver first; `aco` spawns the `appium` binary
13
+ from your `PATH`. See the [Appium install guide](https://appium.io/docs/en/latest/quickstart/install/)
14
+ for details.
15
+
16
+ ```sh
17
+ npm i -g appium # needs Node.js LTS and npm >=10
18
+ which appium # confirm it's on PATH
19
+
20
+ appium driver install xcuitest # iOS (requires Xcode + command line tools)
21
+ appium driver install uiautomator2 # Android (requires Android SDK + JDK)
22
+
23
+ appium driver doctor xcuitest # verify a driver's toolchain
24
+ ```
25
+
26
+ ## Install
27
+
28
+ ```sh
29
+ npm i -g @tai2/aco
30
+ # or run without installing:
31
+ npx @tai2/aco --help
32
+ ```
33
+
34
+ ## Usage
35
+
36
+ ### Discover devices
37
+
38
+ List iOS Simulators, Android AVDs, and connected real devices. Pass a row's
39
+ `NAME` to `--device-name` (iOS) / `--avd` (Android emulator), or its `ID` to
40
+ `--udid` (real device or simulator).
41
+
42
+ ```sh
43
+ aco device list # both platforms, only "available" rows
44
+ aco device list --platform ios # iOS Simulators + connected iPhones/iPads
45
+ aco device list --state all --json # everything, machine-readable
46
+ ```
47
+
48
+ ### Start a session
49
+
50
+ ```sh
51
+ # iOS simulator (foreground; Ctrl-C tears it down)
52
+ aco session start --platform ios --app /tmp/MyApp.app --device-name "iPhone 15"
53
+
54
+ # Android emulator
55
+ aco session start --platform android --app com.example.app --app-activity .MainActivity --avd Pixel_8_API_34
56
+
57
+ # iOS real device (requires code signing for the on-device WebDriverAgent build)
58
+ aco session start --platform ios --udid <40-char-udid> \
59
+ --app /tmp/MyApp.ipa --xcode-org-id ABCDE12345
60
+
61
+ # Android real device (auto-selected when one is plugged in and no --avd given)
62
+ aco session start --platform android --app com.example.app --app-activity .MainActivity
63
+
64
+ # Background instead of foreground
65
+ aco session start --detach --platform ios --app /tmp/MyApp.app
66
+
67
+ # Forward extra Appium server flags
68
+ aco session start --platform android --log-level debug --use-plugins images
69
+
70
+ # Remote server / device farm: --server-url attaches to a running Appium
71
+ # instead of spawning one. --auth sends BASIC auth (only on session creation;
72
+ # or via ACO_REMOTE_USERNAME / ACO_REMOTE_PASSWORD).
73
+ aco session start --platform android --server-url https://grid.example.com/wd/hub \
74
+ --auth user:accessKey --cap deviceName="Pixel 8"
75
+
76
+ # Device farm with vendor-specific nested caps (LambdaTest's "lt:options",
77
+ # BrowserStack's "bstack:options", ...): pass the whole W3C caps object with
78
+ # --caps-json (or --caps-json @file). Replaces the aco-built caps; --platform
79
+ # is still required.
80
+ aco session start --platform android \
81
+ --server-url https://mobile-hub.lambdatest.com/wd/hub --auth user:accessKey \
82
+ --caps-json '{"platformName":"android","lt:options":{"isRealMobile":true,"platformVersion":"13","deviceName":"Pixel 8","app":"lt://APP_ID"}}'
83
+ ```
84
+
85
+ - With neither `--udid` nor `--avd`, a connected real device wins; otherwise the
86
+ first Android AVD is auto-booted. Explicit `--udid`/`--avd` always win.
87
+ - iOS real devices need `--xcode-org-id` (plus optional `--xcode-signing-id`,
88
+ `--allow-provisioning-device-registration`, `--updated-wda-bundle-id`).
89
+ - `--log` streams the Appium log to stdout. `aco session start --help` lists the
90
+ forwarded server flags (`--log-level`, `--relaxed-security`, the `*-timeout`
91
+ knobs, ...).
92
+
93
+ ### Drive the session
94
+
95
+ `--session`, `--server-url`, and `--platform` are optional with a live local
96
+ session; pass them explicitly for remote/grid sessions.
97
+
98
+ ```sh
99
+ aco source # full page source
100
+ aco source --xpath '//XCUIElementTypeButton[@name="Login"]' # filter locally
101
+ aco elements # labelled elements + tap selectors
102
+ aco elements --json | jq -r '.[].selector' # just the selectors
103
+ aco screenshot --out ./shot.png
104
+ aco tap --x 100 --y 200
105
+ aco tap --selector 'accessibility id:login.button'
106
+ aco swipe --direction up # within the default scroll view
107
+ aco swipe --direction left --label home.carousel # within a labelled element
108
+ aco send-keys --selector 'accessibility id:login.username' --text 'alice' # clears, then types
109
+ aco send-keys --label login.username --text '!' --no-clear # append instead
110
+ aco scroll-into-view "accessibility id:gestures.row.29" --direction up # swipe until visible
111
+ aco actions --gesture "move 200 600 0, down, move 200 200 300, up" # raw W3C pointer
112
+ aco actions --type "hello" # raw W3C key
113
+ aco element find --using "accessibility id" --value "Login"
114
+ aco element click --element <element-id>
115
+ aco context list
116
+ aco context switch --name WEBVIEW_com.example # enter the web context, then:
117
+ aco web url https://example.com # navigate the active WebView
118
+
119
+ # Explicit targeting (remote/grid):
120
+ aco source --session <sid> --server-url http://10.0.0.5:4799 --platform ios
121
+ ```
122
+
123
+ ### Platform `mobile:` extensions
124
+
125
+ Every `mobile:` extension the drivers advertise is a first-class command under a
126
+ platform namespace. Flags map 1:1 to the driver's params and coerce to the
127
+ declared type.
128
+
129
+ ```sh
130
+ aco ios --help # all XCUITest mobile: extensions
131
+ aco android --help # all UiAutomator2 / Android extensions
132
+ aco ios swipe --direction up
133
+ aco ios scroll --toVisible true --distance 0.5
134
+ aco android shell --command "getprop ro.product.model"
135
+ aco ios <cmd> --help # see each param's type
136
+ ```
137
+
138
+ `mobile:` names are snake-cased to subcommands (`mobile: doubleTap` →
139
+ `aco ios double-tap`); `--<param>` flags keep the driver's camelCase names.
140
+
141
+ ```sh
142
+ aco mobile list # what the connected driver actually advertises
143
+ aco mobile call --name "mobile: swipe" --args '{"direction":"up"}' # unvalidated escape hatch
144
+ ```
145
+
146
+ ### Inspect / stop sessions
147
+
148
+ ```sh
149
+ aco session list # startedAt, platform, pid, alive, url, sessionId
150
+ aco session list --json
151
+ aco session list --prune # delete records for dead servers / crashed children
152
+
153
+ aco session stop # stop the latest live session
154
+ aco session stop --session <sid> # stop a specific one
155
+ aco session stop --all # stop every stored session
156
+ ```
157
+
158
+ ## Troubleshooting
159
+
160
+ - **`Insecure feature 'adb_shell' not enabled`** when calling `mobile: shell` on
161
+ Android: start the session with `--cap appium:allowInsecure='["adb_shell"]'`.
162
+ - **`appium not found on PATH`** when running `aco session start`: install Appium
163
+ (`npm i -g appium`) and verify `which appium` resolves.
164
+ - **`unknown command (script)`** from `aco mobile call` or a generated
165
+ `aco ios`/`aco android` command: the connected server runs a driver version
166
+ that does not expose that extension. Run `aco mobile list` to see what it
167
+ advertises.
168
+
169
+ ## Development
170
+
171
+ Tool versions are pinned in `mise.toml` -- install [mise](https://mise.jdx.dev)
172
+ and run `mise install` to match.
173
+
174
+ ```sh
175
+ pnpm install
176
+ pnpm dev --help # one-shot run via tsx
177
+ pnpm dev:watch --help # rerun on file changes
178
+ pnpm typecheck # tsc --noEmit
179
+ pnpm test # vitest run
180
+ pnpm gen:extensions # regenerate src/data/extensions-*.json from driver source
181
+ pnpm build # produce dist/cli.js via tsup
182
+ ```
183
+
184
+ See `CLAUDE.md` for the driver-snapshot workflow and the rules for adding new
185
+ `mobile:` wrappers.
186
+
187
+ ## Testing
188
+
189
+ An example Expo-based AUT (App Under Test) lives under [`aut/`](./aut/), with one
190
+ screen per `aco` command family.
191
+
192
+ ```sh
193
+ pnpm aut:install # install AUT deps (~200MB, one-time)
194
+ pnpm aut:prebuild # generate aut/ios and aut/android
195
+ pnpm aut:build:ios # build .app for the iOS Simulator
196
+ pnpm aut:build:android # build .apk for an Android emulator
197
+ ```
198
+
199
+ See [`aut/README.md`](./aut/README.md) for the screen-to-command map.
200
+
201
+ ## License
202
+
203
+ MIT