# Agent runbook: Windows wireless Android control

Use this runbook for setup, repair, diagnosis, and verification. Keep the phone owner present for first pairing.

## Compatibility gate

This packaged project supports a Windows 10/11 computer controlling an Android 11+ phone or tablet. Stop before installation for iPhone/iPad (iOS/iPadOS) or a macOS/Linux computer. Upstream scrcpy may support Android from other desktop systems, but this repository's PowerShell, VBS, WinGet, and `.lnk` workflow is not packaged or tested for them.

Verify the actual host OS and target platform; do not infer them from the product name. Android menus and extra control permissions vary by manufacturer and system version. Do not assume a manufacturer: vendor names below identify conditional, observed workarounds, not a required or default device.

## 0. Keep the human side minimal

The agent owns all Windows-side work. Ask the phone owner only to:

1. use the same trusted Wi-Fi as the computer;
2. enable Developer options and Wireless debugging;
3. open **Pair device with pairing code**;
4. provide the temporary six-digit code and keep that screen open;
5. unlock or confirm an Android security prompt when required.

Do not send a non-technical user to WinGet, PowerShell, ADB, mDNS output, IP addresses, shortcut properties, or test commands. Explain recovery as phone actions first. Expose manual computer steps only when the user explicitly asks or the agent lacks machine access.

## 1. Establish facts

Check:

```powershell
$PSVersionTable.PSVersion
Get-Command winget, adb, scrcpy, wscript, powershell -ErrorAction SilentlyContinue
```

Find existing official scrcpy installs before downloading anything. A verified installation normally contains both `scrcpy.exe` and `adb.exe`.

Do not infer success from PATH alone. Run:

```powershell
& "<scrcpy-dir>\scrcpy.exe" --version
& "<scrcpy-dir>\adb.exe" version
```

## 2. Install only from an official source

Preferred Windows install:

```powershell
winget install --exact Genymobile.scrcpy
```

Alternative: download the Windows archive linked from:

- `https://github.com/Genymobile/scrcpy`
- `https://github.com/Genymobile/scrcpy/blob/master/doc/windows.md`

The scrcpy repository states that its GitHub repository is the only official source. Do not use mirrors or repack sites. Check the release checksum when installing from a ZIP.

The scripts were forward-run on scrcpy 4.0 with ADB 37 on Windows 11. They do not pin a scrcpy version. Recheck the official release page for the current version; do not claim an untested upgrade has been validated.

## 3. Pair once, interactively

Requirements:

- Android phone: Android 11 or newer.
- Windows computer and phone: same trusted Wi-Fi.
- Phone: Developer options and Wireless debugging enabled.
- Avoid guest Wi-Fi, public Wi-Fi, client isolation, VPN paths that block local multicast, and router port forwarding.

Open **Wireless debugging > Pair device with pairing code** on the phone. Ask for the six-digit code only after exactly one pairing service is discoverable.

For agent-completed pairing in a non-interactive execution surface that does not persist shell history, pass the code through a process-scoped environment variable:

```powershell
$env:APU_PAIRING_CODE = "<six-digit-code>"
try {
    powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".\scripts\pair-android-wireless.ps1"
} finally {
    Remove-Item Env:APU_PAIRING_CODE -ErrorAction SilentlyContinue
}
```

The helper validates exactly six ASCII digits, reuses official-tool discovery, accepts exactly one pairing service, pipes the code to ADB through standard input, and clears its inherited environment copy. It does not pass the code in the ADB argument list or store it in a file, config, or launcher log.

Do not echo the actual command, code, or environment value in commentary or the final response. Do not place it in persistent shell history, a reusable script, or a shell profile. The private task transcript may already contain the one-time code because the owner supplied it; do not replicate it into additional surfaces.

In an interactive terminal, omit `APU_PAIRING_CODE` and use the agent's input-control capability to type at ADB's prompt. The owner may instead choose to type it personally.

For manual diagnosis, run:

```powershell
& "<scrcpy-dir>\adb.exe" mdns services
```

On current ADB versions, `adb server-status` should report mDNS enabled and the recommended `LIBADBMDNS` backend. For a deeper network-only diagnosis, `adb mdns track-services --proto-text` can show whether TLS services are arriving at all. Its raw output may include the phone model, given name, hostname, service instance, IP addresses, and serial; redact it before sharing or saving evidence.

Distinguish the services:

- `_adb-tls-pairing._tcp`: temporary pairing endpoint.
- `_adb-tls-connect._tcp`: ordinary connection endpoint after pairing.

The pairing screen and connect service may show different ports. This is normal. Prefer the endpoint on the matching mDNS service when available. Run:

```powershell
& "<scrcpy-dir>\adb.exe" pair <pairing-ip>:<pairing-port>
```

For manual diagnosis, never put the code in the ADB command-line argument list, a file, or a log.

Pairing usually persists until the user forgets the computer or revokes ADB authorizations. The **Wireless debugging switch is separate** and may be off after a reboot, a network change, or Android power/security management. Do not tell the user to re-pair until mDNS and the switch have been checked.

On some manufacturer builds, mirroring may work while mouse or keyboard injection fails. Follow the observed error and that device's documented security setting. For example, on some Xiaomi/Redmi builds the relevant developer option is named **USB debugging (Security settings)** and may require a phone reboot. Do not assume this label exists elsewhere, and do not disable other security controls.

## 4. Install or repair the shortcut

From the skill directory:

```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".\scripts\install-shortcut.ps1"
```

For a manually extracted official release that automatic discovery cannot find:

```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".\scripts\install-shortcut.ps1" -ScrcpyDir "<official-scrcpy-folder>"
```

The installer:

- copies the runtime files to `%LOCALAPPDATA%\AgentPhoneUse`;
- writes only the scrcpy tool directory to local `config.json`;
- creates `连接 Android 手机.lnk` on a Chinese Windows UI or `Connect Android Phone.lnk` on other Windows UI languages;
- targets `wscript.exe`, which calls `start-hidden.vbs`, so no terminal window appears;
- backs up changed launchers and preserves a conflicting same-name shortcut outside the desktop before replacing it;
- on the default install path, checks both the current-user and common desktop sources, then moves recognized old managed shortcuts and the old `android-wireless-control` runtime out of active locations after the new entry is ready;
- notifies Windows Explorer after shortcut create, update, or migration so a removed alias does not remain as a stale desktop icon;
- fingerprints shortcut target and runtime before migration, so an unrelated product-named shortcut is left untouched and setup stops with an explicit conflict instead of silently claiming one desktop entry.

It does not store a phone IP, endpoint, serial, pairing code, or runtime log in the skill.

Custom `-InstallDir` and `-ShortcutPath` targets do not touch default legacy locations unless legacy paths are explicitly passed. Use `-SkipLegacyMigration` when an old installation must remain untouched.

## 5. Verify with ground truth

Check tools:

```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".\scripts\start-agent-phone-use.ps1" -ToolsOnly -NoGui
```

Check mDNS, connect, and exact ADB `device` state without opening scrcpy:

```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".\scripts\start-agent-phone-use.ps1" -SelfCheck -NoGui
```

Read the current localized shortcut back across the Windows desktop sources that Explorer merges and require exactly one managed entry:

```powershell
$desktops = @(
    [Environment]::GetFolderPath('DesktopDirectory'),
    [Environment]::GetFolderPath('CommonDesktopDirectory')
) | Where-Object { $_ } | Sort-Object -Unique
$names = @('连接 Android 手机.lnk', 'Connect Android Phone.lnk')
$paths = @($desktops | ForEach-Object {
    $desktop = $_
    $names | ForEach-Object {
        $candidate = Join-Path $desktop $_
        if (Test-Path -LiteralPath $candidate -PathType Leaf) { $candidate }
    }
})
if ($paths.Count -ne 1) { throw "Expected one current shortcut; found $($paths.Count)." }
$p = $paths[0]
$s = (New-Object -ComObject WScript.Shell).CreateShortcut($p)
$s | Select-Object TargetPath, Arguments, WorkingDirectory, IconLocation
```

Confirm:

- target is `%WINDIR%\System32\wscript.exe`;
- arguments point to `%LOCALAPPDATA%\AgentPhoneUse\start-hidden.vbs`;
- both the target and VBS exist;
- no recognized previous managed shortcut remains active in either user or common desktop;
- after a rename or migration, Windows Explorer visually shows one entry; if the filesystem and Shell namespace show one but the screen still shows two, refresh the desktop before declaring failure or success;
- no engineering or test directory was added to the real user or common desktop. In particular, `.agents`, `.codex`, `.git`, fixture, backup, and test-root directories do not belong there; keep all test roots under the system temporary directory and all recoverable backups under the runtime backup directory;
- `-SelfCheck` exits 0 and prints exactly one `READY <endpoint>` line;
- a real shortcut launch produces a scrcpy window and the new `scrcpy.exe` process remains alive.
- a second shortcut launch while the first control chain is alive exits quietly and does not spawn another scrcpy;
- a locked primary log cannot change a successful launch into a failure.

When validating a repair, check the process path, runtime log, and the complete immediate directory set of both desktop roots—not only the shortcut timestamp or `.lnk` count. Logs live under `%LOCALAPPDATA%\AgentPhoneUse\logs\`.

Create at least one failure canary. For example, this must exit non-zero:

```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".\scripts\start-agent-phone-use.ps1" -ToolsOnly -NoGui -ScrcpyDir "C:\definitely-not-scrcpy"
```

Also scan the deliverable before publication:

```powershell
python ".\tests\publication_scan.py"
```

The scanner permits documentation-only RFC 5737 endpoints and explicit `EXAMPLE` fixtures. Real endpoints, service instances, device serials, usernames, pairing codes, and logs are not.

## 6. Diagnose safely

### No `_adb-tls-connect._tcp` result

1. Wake and unlock the phone.
2. Verify Wireless debugging is on.
3. Verify both devices are on the same trusted Wi-Fi, not a guest network.
4. Toggle Wireless debugging off and on.
5. Re-run `adb mdns services`.
6. Run `adb server-status` when supported and inspect `mdns_enabled` and the backend. On ADB 37+, prefer the recommended `LIBADBMDNS` backend.
7. If available, briefly run `adb mdns track-services --proto-text` to distinguish “no multicast service reaches this PC” from a parser or stale-state problem; do not publish its raw identifying fields.
8. Only after collecting the current state, restart ADB with `adb kill-server` then `adb start-server`.
9. If mDNS remains empty, inspect AP/client isolation and local firewall rules. Do not open public ports.

Phrase the result accurately: no connectable Wireless debugging service was discovered. Pairing may still be saved. A real session has shown the switch turning off mid-control while the paired-computer record remained; reopening the switch, waking, and unlocking restored the existing shortcut without re-pairing. Reboot, network change, power management, or system security management are possible contributors, not confirmed causes unless evidence identifies one.

### Pairing succeeds but daily launch fails

- Do not reuse the pairing port for `adb connect`.
- Re-run `adb mdns services` and use `_adb-tls-connect._tcp`.
- After selecting the endpoint, run device-specific checks as `adb -s <selected-endpoint> get-state`; do not use a bare `adb shell`.
- Confirm the Wireless debugging switch, then re-pair only if the paired computer entry is gone or was explicitly revoked.

### Duplicate ADB rows or duplicate launch

- One physical phone may appear in `adb devices` under both an endpoint and an mDNS transport alias. Do not infer physical-device count from row count.
- Use `_adb-tls-connect._tcp` discovery to choose the endpoint, then keep every device-specific command pinned with `adb -s <selected-endpoint>`.
- Distinguish this from two real devices: multiple connect services remain an ambiguity and must fail safely.
- The launcher uses a Windows named mutex for one active control chain. A second desktop launch while the first is alive should exit 0 without opening an error dialog or another scrcpy.
- It also checks for a live `scrcpy.exe` from the same resolved tool installation, covering a manually started scrcpy process that has no launcher mutex. Do not terminate or activate that process; exit quietly.
- Logging is best effort. The primary log uses a separate mutex, retry, shared-read/write file access, and a per-process fallback; all logging failures are swallowed after fallback so they cannot determine control success.

### Multiple connect services

Stop. Do not select the first service. Ask the user to disable Wireless debugging on the other devices, then re-run discovery.

### Mirror opens but control is blocked

- Check a manufacturer-specific input security setting only when the device reports that input injection is denied; the Xiaomi/Redmi label above is one conditional example, not a universal step.
- Lock screens, biometrics, payment/banking screens, DRM surfaces, enterprise policies, and app-specific secure windows remain enforced. Use the phone directly.

### Performance is poor

Keep the same local Wi-Fi, move closer to the access point, and reduce resolution with a scrcpy argument such as `--max-size=1024`. Do not misrepresent Wi-Fi mirroring as internet remote control.

### Keyboard, IME, clipboard, or ADB version conflicts

- scrcpy's default `--keyboard=sdk` is strongest for ASCII and may not inject every character. For sustained multilingual typing, evaluate `--keyboard=uhid`; it works over TCP/IP and with IMEs, but requires one-time physical-keyboard layout configuration on the phone.
- Clipboard synchronization exposes pasted computer clipboard data to the Android clipboard, which apps may read. Never paste passwords, recovery codes, or secrets through it. Use `--no-clipboard-autosync` when clipboard sharing is unnecessary.
- Do not mix unrelated ADB binaries. A server/client version mismatch can make a Windows tool conflict look like a phone failure. Keep scrcpy and the sibling `adb.exe` from the same official package.

## 7. Operate a scrcpy window with Computer Use

- Windows Graphics Capture may observe an occluded scrcpy window, but click/type injection still uses foreground Windows input and may steal focus or collide with the user's mouse and keyboard. Tell the user to pause briefly during consequential interaction. Do not describe this as isolated background control.
- After click, `Alt+h`, or `Alt+b`, refresh once to establish the result boundary, wait about 0.5–1.2 seconds, then observe again. Continue only after the target state is stable. Never reuse stale screenshot IDs or coordinates.
- Treat `Alt+h` as Home and `Alt+b` as Back; both have real-operation evidence.
- Before Chinese input, verify the keyboard and input caret. After `type_text`, allow about 0.7 seconds for IME composition to commit, then verify the complete text and enabled send control. Candidate-bar text from another app is not proof that the current field contains it.
- When direct Chinese launcher search is unstable, ASCII pinyin can be a tested fallback; `weixin` and `xiaohongshu` were observed on one Xiaomi launcher and must not be assumed universal.
- Stop on any manufacturer dual-app/app-clone chooser unless the user confirms main versus clone, or account/contact verification inside the app disambiguates it.
- For outbound messaging, confirm app, account, recipient, and full content at action time. After sending, re-read the conversation and require the sender-side message bubble as ground truth.

Real end-to-end evidence exists for opening the main WeChat and Xiaohongshu apps, navigating to a specified private conversation, reading context, entering a long Chinese message, sending it, and reading back the sender-side bubble. Treat these as proven interaction patterns, not proof that every app or account is safe to automate.

For repeated or high-consequence flows, prefer a semantic Android control surface over screenshot coordinates when available. Android UI Automator provides element predicates, built-in timeouts, app-visibility checks, and stable-window waits. Third-party mobile MCPs can expose similar capabilities, but review source, maintenance, telemetry, device-selection rules, arbitrary-shell tools, and network listeners before installation. Never let an MCP default to “the first device” when device identity matters.

## 8. Regression checklist

1. Wireless debugging off while the paired-computer record remains.
2. Mid-session disconnect followed by switch re-enable and reconnect without pairing.
3. Concurrent double launch, externally locked log, and an already-running scrcpy.
4. One physical phone represented by two ADB transport aliases.
5. Two real connect services fail without guessing.
6. Navigation animation requires a fresh delayed observation.
7. Chinese IME composition commits before send.
8. Manufacturer dual-app/app-clone ambiguity stops for confirmation.
9. Outbound send is complete only after reading back the sender-side bubble.