@lingxia/skill 0.8.0 → 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/package.json +1 -1
- package/skill/SKILL.md +1 -0
- package/skill/cli/reference.md +2 -0
- package/skill/skill-manifest.json +2 -2
- package/skill/cli/lxdev.md +0 -195
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lingxia/skill",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Agent skill for the LingXia cross-platform app framework. Installs a markdown skill bundle into your project so AI coding tools — Claude Code, Claude Agent SDK, OpenAI Codex, Cursor, or any agent that reads project markdown — can build lxapps, host apps, and native Rust extensions on LingXia.",
|
|
6
6
|
"type": "module",
|
package/skill/SKILL.md
CHANGED
|
@@ -91,6 +91,7 @@ For the full surface of `lx.*` and which namespace covers what, see [`./lxapp/lx
|
|
|
91
91
|
| Need | File |
|
|
92
92
|
|---|---|
|
|
93
93
|
| Every CLI command, flag, env var (daily use) | [`./cli/reference.md`](./cli/reference.md) |
|
|
94
|
+
| Drive a running `lingxia dev` session (`lxdev`: browser/app/lxapp/logs automation) | [`./cli/lxdev.md`](./cli/lxdev.md) |
|
|
94
95
|
| Page authoring: `Page({})`, `useLxPage`, events | [`./lxapp/guide.md`](./lxapp/guide.md) |
|
|
95
96
|
| **Native components: `LxInput`, `LxVideo`, `LxMediaSwiper`, `LxPicker`, `LxNavigator`, `LxTextarea`** | [`./lxapp/components.md`](./lxapp/components.md) |
|
|
96
97
|
| **Logic-side `lx.*` API surface map** | [`./lxapp/lx-api.md`](./lxapp/lx-api.md) |
|
package/skill/cli/reference.md
CHANGED
|
@@ -205,6 +205,8 @@ lingxia dev --release
|
|
|
205
205
|
|
|
206
206
|
> **Note:** For standalone lxapp projects, `--device`, `--abis`, and non-macOS `--platform` are not supported. Runner currently launches locally on macOS.
|
|
207
207
|
|
|
208
|
+
> **Driving a live session:** once `lingxia dev` is running, use the separate **`lxdev`** binary to automate the running app — open URLs, click/type/eval in browser tabs and lxapp pages, screenshot windows, and tail logs without restarting. See [`lxdev` — Drive a running dev session](./lxdev.md).
|
|
209
|
+
|
|
208
210
|
---
|
|
209
211
|
|
|
210
212
|
### `lingxia install`
|
package/skill/cli/lxdev.md
DELETED
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
# `lxdev` — Drive a running dev session
|
|
2
|
-
|
|
3
|
-
`lxdev` is the external automation client for a running LingXia `lingxia dev` session. It ships from the same crate as `lingxia` and is on `PATH` after a standard install. Use it to inspect / drive the host app's browser tabs, the lxapps inside it, and the dev log stream — without rebuilding or restarting the dev session.
|
|
4
|
-
|
|
5
|
-
This is the **agent-facing** dev surface: every command takes plain flags, prints predictable JSON (with `--json`), and never owns a long-running process. Run it from anywhere inside the project tree.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## How it finds the session
|
|
10
|
-
|
|
11
|
-
`lingxia dev` writes one file per active session under `.lingxia/sessions/<session_id>.json` and removes it on clean exit. `lxdev` scans that directory on every invocation. Each file records:
|
|
12
|
-
|
|
13
|
-
| Field | Purpose |
|
|
14
|
-
|---|---|
|
|
15
|
-
| `session_id` | `<unix-ms>-<uuid>`; stable for the whole session |
|
|
16
|
-
| `pid` | The `lingxia dev` process — diagnostics only |
|
|
17
|
-
| `platform` | `android` / `ios` / `macos` / `harmony` / `lxapp` |
|
|
18
|
-
| `started_at` | Unix milliseconds |
|
|
19
|
-
| `ws_url` | `ws://host:port` the dev websocket is listening on |
|
|
20
|
-
| `log_file` | Path to the session's JSONL log file |
|
|
21
|
-
|
|
22
|
-
There is no daemon. The CLI process that started the session owns its file; nothing else writes there.
|
|
23
|
-
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
## Selecting a session
|
|
27
|
-
|
|
28
|
-
When `lxdev` is invoked **without** `--session` or `--platform`:
|
|
29
|
-
|
|
30
|
-
- **One live session in the project** → use it (no probe).
|
|
31
|
-
- **Multiple live sessions** → refuse and list candidates. The user must add `--session <id-prefix>` or `--platform <name>`.
|
|
32
|
-
|
|
33
|
-
Why refuse rather than pick a default? In a project where a human and an agent (Claude / Codex / CI) might both be running dev sessions concurrently, "default to the most recent" silently routes commands to the wrong target. Explicit selection beats a guess.
|
|
34
|
-
|
|
35
|
-
Flags (both are global — they go before the subcommand):
|
|
36
|
-
|
|
37
|
-
```bash
|
|
38
|
-
lxdev --session 20260520-abc browser tabs
|
|
39
|
-
lxdev --platform ios browser tabs
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
`--session` matches by prefix, so a short unique fragment is enough. `--platform` is exact (case-insensitive). Selectors error out if zero or multiple sessions match.
|
|
43
|
-
|
|
44
|
-
---
|
|
45
|
-
|
|
46
|
-
## `lxdev sessions`
|
|
47
|
-
|
|
48
|
-
Inspect / clean up session state:
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
lxdev sessions # human-readable table
|
|
52
|
-
lxdev sessions --json # JSON array — each entry has a `stale` boolean
|
|
53
|
-
lxdev sessions prune # remove session files whose WS server no longer responds
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
A session is considered **stale** when a 200ms TCP probe to its `ws_url` fails. Stale entries are normally cleaned up automatically — by the next `lingxia dev` startup (which prunes before checking same-platform conflicts), and by `lxdev` when ambiguity forces it to probe. `lxdev sessions prune` is the manual escape hatch after a hard crash (`kill -9`, IDE force-stop, etc.).
|
|
57
|
-
|
|
58
|
-
---
|
|
59
|
-
|
|
60
|
-
## Subcommand families
|
|
61
|
-
|
|
62
|
-
`lxdev` exposes four families of commands, all of which target a single resolved session:
|
|
63
|
-
|
|
64
|
-
### `lxdev browser …`
|
|
65
|
-
|
|
66
|
-
Drive the host app's browser tabs. Roughly a subset of Playwright's automation surface, scoped to a single LingXia browser instance:
|
|
67
|
-
|
|
68
|
-
`open`, `tabs`, `current`, `activate`, `close`, `reload`, `back`, `forward`, `eval`, `query`, `wait`, `wait-url`, `wait-navigation`, `click`, `type`, `fill`, `press`, `scroll`, `scroll-to`, `cookies list|set|delete|clear`, `screenshot`.
|
|
69
|
-
|
|
70
|
-
Most subcommands accept `--tab current|<tab-id>` (default: `current`) and `--json`. Wait/navigation commands take `--timeout-ms`.
|
|
71
|
-
|
|
72
|
-
**Screenshot** captures a PNG of the tab's visible content via the platform WebView's native snapshot API. By default writes to `.lingxia/screenshots/<tab>-<ts>.png`; pass `--output <path>` or `--output -` for stdout, or `--json` to get the base64-encoded payload inline.
|
|
73
|
-
|
|
74
|
-
This is the **WebView-scope** screenshot — only web content, no host UI overlays. For the entire window (including native sidebars, surfaces, etc.) see `lxdev app screenshot` below.
|
|
75
|
-
|
|
76
|
-
| Platform | WebView screenshot | App/window screenshot |
|
|
77
|
-
|---|---|---|
|
|
78
|
-
| macOS | ✅ WKWebView `takeSnapshotWithConfiguration:` → `NSImage` → `NSBitmapImageRep` PNG | ✅ `NSView.cacheDisplayInRect:toBitmapImageRep:` (no Screen Recording permission needed) |
|
|
79
|
-
| iOS | ✅ WKWebView `takeSnapshotWithConfiguration:` → `UIImagePNGRepresentation` | ✅ `UIWindow.layer.renderInContext:` (key UIWindow via scene + fallback chain) |
|
|
80
|
-
| Android | ✅ `WebView.draw(Canvas)` onto a `Bitmap` → `Bitmap.compress(PNG)` via JNI | ✅ `PixelCopy.request(window.decorView)` (API 26+) → `View.draw(Canvas)` fallback |
|
|
81
|
-
| HarmonyOS | ✅ `WebviewController.webPageSnapshot` → `image.PixelMap` → `ImagePacker` PNG | ✅ `window.snapshot` → `ImagePacker` PNG |
|
|
82
|
-
|
|
83
|
-
All platforms time out after 5 seconds. The PNG bytes are returned to the CLI base64-encoded in the JSON envelope; `lxdev` decodes and writes the binary file.
|
|
84
|
-
|
|
85
|
-
### `lxdev app …`
|
|
86
|
-
|
|
87
|
-
Operate at the host-app scope (not lxapp-scope): window enumeration and full window screenshot.
|
|
88
|
-
|
|
89
|
-
```bash
|
|
90
|
-
lxdev app windows # list all NSWindow / Activity / UIWindow
|
|
91
|
-
lxdev app windows --json # same as JSON
|
|
92
|
-
lxdev app screenshot # capture key/focused window
|
|
93
|
-
lxdev app screenshot --scope screen # full device display (default off iOS)
|
|
94
|
-
lxdev app screenshot --scope window # app's own window only (default on iOS)
|
|
95
|
-
lxdev app screenshot --window <id> # specific window (id from `app windows`); window scope only
|
|
96
|
-
lxdev app screenshot --output ~/x.png # custom path; default .lingxia/screenshots/app-<platform>-<ts>.png
|
|
97
|
-
lxdev app screenshot --output - # PNG bytes to stdout
|
|
98
|
-
lxdev app screenshot --json # JSON envelope (window-scope only — screen scope writes a file)
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
#### Scope: `screen` vs `window`
|
|
102
|
-
|
|
103
|
-
These two scopes capture **different things**; the same command produces different output across platforms because Apple's iOS doesn't expose a host-side screen-capture CLI.
|
|
104
|
-
|
|
105
|
-
- **`screen`** — full device display via host tools (`adb shell screencap` / `hdc shell snapshot_display` / `screencapture`). Includes IME, status bar, dialogs from other windows, system overlays. No in-app code, no consent prompt, no foreground service. Default on android / harmony / macos.
|
|
106
|
-
- **`window`** — only the app's own window via the in-app `PixelCopy` / `webPageSnapshot` / `UIWindow.layer.render` path. Excludes IME and system bars. Required default on **iOS** (no public CLI screen capture) and the only way to target a specific `--window` on multi-window platforms (macOS).
|
|
107
|
-
|
|
108
|
-
| Platform | Default | `--scope screen` | `--scope window` |
|
|
109
|
-
|---|---|---|---|
|
|
110
|
-
| android | screen | adb screencap (full incl. IME) | PixelCopy (app window) |
|
|
111
|
-
| harmony | screen | hdc snapshot_display (full incl. IME) | webPageSnapshot (app window) |
|
|
112
|
-
| macos | screen | screencapture (full display) | NSWindow capture |
|
|
113
|
-
| **ios** | **window** | **errors — Apple platform limit** | UIWindow.layer.render |
|
|
114
|
-
|
|
115
|
-
If you're using `lxdev` to verify a layout change against an IME / keyboard scenario, you need `--scope screen` (the default everywhere except iOS). On iOS that case can only be verified manually because there's no CLI screen-capture tool — Apple does not expose one through `xcrun devicectl` today.
|
|
116
|
-
|
|
117
|
-
**Multi-window** matters mainly on desktop. On macOS, `lx.surface({kind:'window'})` creates a separate NSWindow. Use `lxdev app windows` to enumerate; `--window <id>` selects one in `window` scope (the `id` is the platform-native window number — NSWindow.windowNumber on macOS, HWND on future Windows). Mobile platforms have a single foreground window and `--window` is ignored.
|
|
118
|
-
|
|
119
|
-
#### How `screen` finds the right device
|
|
120
|
-
|
|
121
|
-
`lingxia dev` set up an `adb forward` / `hdc fport` mapping when it created the session — the port forward is the only persistent record of which physical device this session belongs to. `lxdev` discovers the device at screenshot time by reading `adb forward --list` (or `hdc fport ls`) and matching its `ws_url` port against the host side of every forward. No device id is duplicated into session metadata, so there's nothing to keep in sync — the forward table is the source of truth.
|
|
122
|
-
|
|
123
|
-
### `lxdev lxapp …`
|
|
124
|
-
|
|
125
|
-
Manage lxapps running inside the session:
|
|
126
|
-
|
|
127
|
-
`list`, `current`, `info`, `pages`, `page`, `eval`, `open`, `close`, `restart`, `uninstall`.
|
|
128
|
-
|
|
129
|
-
`lxdev lxapp eval` runs JavaScript inside the lxapp's Logic runtime (AppService); useful for inspecting state or invoking actions without a UI round-trip.
|
|
130
|
-
|
|
131
|
-
### `lxdev logs`
|
|
132
|
-
|
|
133
|
-
Tail and filter the session log stream:
|
|
134
|
-
|
|
135
|
-
```bash
|
|
136
|
-
lxdev logs # last 200 lines
|
|
137
|
-
lxdev logs -f # follow
|
|
138
|
-
lxdev logs -f --level error # filter by level
|
|
139
|
-
lxdev logs --source webview --grep CSP # filter by source + text
|
|
140
|
-
lxdev logs --path pages/home --json # JSONL output
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
Levels: `verbose`, `debug`, `info`, `warn`, `error`.
|
|
144
|
-
Sources: `native`, `webview`, `logic`, `web_view_console`, `lx_app_service_console`.
|
|
145
|
-
|
|
146
|
-
---
|
|
147
|
-
|
|
148
|
-
## Concurrency rules
|
|
149
|
-
|
|
150
|
-
The whole design is built around "a human and one or more agents may be doing dev in parallel." The rules are:
|
|
151
|
-
|
|
152
|
-
1. **`lingxia dev` refuses to start a second same-platform session** unless `--parallel` is passed. This is the primary defense — if you never trip this, you'll never have an ambiguous `lxdev` call.
|
|
153
|
-
2. **`lxdev` refuses to act when ambiguity exists.** It will not silently pick a session for you; it prints the candidates and asks for a `--session` / `--platform`.
|
|
154
|
-
3. **Stale sessions don't count.** Pruning happens in three places (`lingxia dev` startup, `lxdev sessions prune`, and `lxdev` itself when ambiguity forces it), so a hard-crashed `lingxia dev` won't keep blocking future runs.
|
|
155
|
-
4. **`--parallel` is per-launch.** It does not persist; each subsequent `lingxia dev` for that platform must opt in again.
|
|
156
|
-
|
|
157
|
-
---
|
|
158
|
-
|
|
159
|
-
## Typical agent flow
|
|
160
|
-
|
|
161
|
-
```bash
|
|
162
|
-
# Discover what's available
|
|
163
|
-
lxdev sessions
|
|
164
|
-
|
|
165
|
-
# Single session, no ambiguity → zero-arg invocation
|
|
166
|
-
lxdev browser open https://example.com
|
|
167
|
-
lxdev browser eval --js "document.title"
|
|
168
|
-
lxdev logs -f --level warn
|
|
169
|
-
|
|
170
|
-
# Visual regression / what-does-the-user-see
|
|
171
|
-
lxdev app windows # see all host windows
|
|
172
|
-
lxdev app screenshot # current focused window
|
|
173
|
-
lxdev browser screenshot # just the web content of the current tab
|
|
174
|
-
|
|
175
|
-
# Two sessions running (e.g. ios + harmony) → disambiguate by platform
|
|
176
|
-
lxdev --platform ios browser tabs
|
|
177
|
-
lxdev --platform harmony logs --grep BridgeError
|
|
178
|
-
|
|
179
|
-
# After a crash leaves residue
|
|
180
|
-
lxdev sessions prune
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
---
|
|
184
|
-
|
|
185
|
-
## Symptom router
|
|
186
|
-
|
|
187
|
-
| Symptom | Fix |
|
|
188
|
-
|---|---|
|
|
189
|
-
| `No active dev session found` | Run `lingxia dev` in this project. |
|
|
190
|
-
| `Multiple active dev sessions match` | Add `--session <prefix>` or `--platform <name>`. |
|
|
191
|
-
| `All matching dev sessions are unreachable` | Run `lxdev sessions prune`, then start a fresh `lingxia dev`. |
|
|
192
|
-
| `Existing <platform> dev session is already running` (from `lingxia dev`) | Stop the other one, or pass `--parallel` if you genuinely want two. |
|
|
193
|
-
| `lxdev` connects but commands hang | The host app likely lost its bridge — restart `lingxia dev`. |
|
|
194
|
-
|
|
195
|
-
For the underlying design rationale (why no daemon, why this specific file layout), see the project draft `docs/draft/dev-session-multi.md` in the LingXia repo.
|