feat: communication scrcpy — Android mirror/control wrapper over scrcpy+adb (devices, record, tcpip, connect, push, pull, screenshot, info)

This commit is contained in:
Your Name
2026-08-13 14:29:09 +00:00
parent a4c025d236
commit 261e4114e2
9 changed files with 375 additions and 18 deletions
+18 -14
View File
@@ -10,19 +10,19 @@
<!-- GEN:START docmap -->
| ## 1. Project Overview | 2843 |
| ## 2. Directory Structure | 44192 |
| ## 3. Installation Flow | 193244 |
| ## 4. The `pos` CLI System | 245314 |
| ## 5. Shared Library — `lib/common.sh` | 315346 |
| ## 6. Docker Compose / ScaleTail | 347389 |
| ## 7. Optional Apps (`apps/`) | 390419 |
| ## 8. Entertainment Module | 420433 |
| ## 9. Systemd Services | 434445 |
| ## 10. Configuration Files | 446472 |
| ## 11. Coding Conventions | 473505 |
| ## 12. Development Workflow | 506558 |
| ## 13. Key File Quick Reference | 559618 |
| ## 14. Common Tasks for Agents | 619648 |
| ## 2. Directory Structure | 44193 |
| ## 3. Installation Flow | 194245 |
| ## 4. The `pos` CLI System | 246316 |
| ## 5. Shared Library — `lib/common.sh` | 317348 |
| ## 6. Docker Compose / ScaleTail | 349391 |
| ## 7. Optional Apps (`apps/`) | 392421 |
| ## 8. Entertainment Module | 422435 |
| ## 9. Systemd Services | 436447 |
| ## 10. Configuration Files | 448474 |
| ## 11. Coding Conventions | 475507 |
| ## 12. Development Workflow | 508560 |
| ## 13. Key File Quick Reference | 561621 |
| ## 14. Common Tasks for Agents | 622652 |
<!-- GEN:END docmap -->
## 1. Project Overview
@@ -64,6 +64,7 @@ Linux_post_install/
│ ├── pos-ai-gemini # Chat with Google Gemini (ask, chat, models, sessions)
│ ├── pos-communication-matrix-listener # Matrix listener: map /command → bash, run them on room messages
│ ├── pos-communication-matrix-sender # Send messages to a Matrix room via the client-server API (send, test, login)
│ ├── pos-communication-scrcpy # Mirror/control an Android device via scrcpy+adb (mirror, devices, record, tcpip, connect, push, pull, screenshot, info)
│ ├── pos-communication-telegram-listener # Telegram bot listener: map /command → bash, run them on chat messages
│ ├── pos-communication-telegram-sender # Send Telegram messages/files/links/stickers via Bot API (send, test)
│ ├── pos-config # Interactive editor for the tools' runtime config (reads # POS_CONFIG: registry)
@@ -264,6 +265,7 @@ All non-interactive `pos` commands log output to `~/.local/share/linux_post_inst
| ai | gemini | `pos-ai-gemini` | Chat with Google Gemini (ask, chat, models, sessions) |
| communication | matrix-listener | `pos-communication-matrix-listener` | Matrix listener: map /command → bash, run them on room messages |
| communication | matrix-sender | `pos-communication-matrix-sender` | Send messages to a Matrix room via the client-server API (send, test, login) |
| communication | scrcpy | `pos-communication-scrcpy` | Mirror/control an Android device via scrcpy+adb (mirror, devices, record, tcpip, connect, push, pull, screenshot, info) |
| communication | telegram-listener | `pos-communication-telegram-listener` | Telegram bot listener: map /command → bash, run them on chat messages |
| communication | telegram-sender | `pos-communication-telegram-sender` | Send Telegram messages/files/links/stickers via Bot API (send, test) |
| | config | `pos-config` | Interactive editor for the tools' runtime config (reads # POS_CONFIG: registry) |
@@ -580,6 +582,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
| `bin/pos-ai-gemini` | 311 | Chat with Google Gemini (ask, chat, models, sessions) |
| `bin/pos-communication-matrix-listener` | 568 | Matrix listener: map /command → bash, run them on room messages |
| `bin/pos-communication-matrix-sender` | 224 | Send messages to a Matrix room via the client-server API (send, test, login) |
| `bin/pos-communication-scrcpy` | 239 | Mirror/control an Android device via scrcpy+adb (mirror, devices, record, tcpip, connect, push, pull, screenshot, info) |
| `bin/pos-communication-telegram-listener` | 566 | Telegram bot listener: map /command → bash, run them on chat messages |
| `bin/pos-communication-telegram-sender` | 221 | Send Telegram messages/files/links/stickers via Bot API (send, test) |
| `bin/pos-config` | 80 | Interactive editor for the tools' runtime config (reads # POS_CONFIG: registry) |
@@ -610,7 +613,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
| `bin/pos-system-health` | 209 | Host health dashboard (disk, RAM, services, backup age, fail2ban, docker); exit 1 if any FAIL |
| `bin/pos-system-schedule` | 81 | Scheduled jobs: run a command on a timer; notify on threshold/change/error/always or silently |
| `bin/pos-tree` | 112 | Show the pos CLI command tree: categories, commands, and subcommands |
| `completions/pos.bash` | 291 | Dynamic bash completion |
| `completions/pos.bash` | 292 | Dynamic bash completion |
<!-- GEN:END filetable -->
| `apps/install.sh` | 171 | App install/uninstall picker/orchestrator |
@@ -639,6 +642,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
| Modify aria2 download daemon / queue logic | Edit `bin/pos-network-download` |
| Modify NFS share logic | Edit `bin/pos-share-nfs-server` / `bin/pos-share-nfs-client` |
| Modify SMB share logic | Edit `bin/pos-share-smb-server` / `bin/pos-share-smb-client` |
| Modify scrcpy mirroring logic | Edit `bin/pos-communication-scrcpy` (config scope `scrcpy` via `pos config scrcpy`; `SCRCPY_*` keys in `~/.config/linux_post_install/scrcpy.env`) |
| Modify the scheduler / scheduled jobs | Edit `bin/pos-system-schedule` / `lib/scheduler-lib.sh` (jobs in `~/.config/linux_post_install/schedule.d/`) |
| Modify AI/Gemini logic | Edit `bin/pos-ai-gemini` (config scope `ai` via `pos config ai`; `AI_GEMINI_API_KEY`/`AI_GEMINI_MODEL` in `~/.config/linux_post_install/ai.env`) |
| Modify UFW/firewall logic | Edit `bin/pos-system-firewall` |
+2 -1
View File
@@ -17,7 +17,7 @@ authoritative one-line reference (every command + flag), see
| `pos system schedule` | Scheduled jobs: run a command on a timer, notify on threshold/change/error or silently | [schedule](howto/schedule.md) |
| `pos ssh` | Load keys into the agent | [ssh](howto/ssh.md) |
| `pos share` | Share USB devices & filesystems over the network (USB, NFS, SMB) | [share](howto/share.md) |
| `pos communication` | Send Telegram/Matrix messages & alerts, /command listeners | [communication](howto/communication.md) |
| `pos communication` | Send Telegram/Matrix messages & alerts, /command listeners, Android mirroring (scrcpy) | [communication](howto/communication.md) |
| `pos entertainment` | Scheduled auto-messages from public APIs | [entertainment](howto/entertainment.md) |
Every tool is `bin/pos-<category>-<command>`; run `pos <category> --help` to
@@ -37,6 +37,7 @@ templates (without overwriting an existing file):
|------|---------|------|
| `telegram.env` | `pos communication telegram sender` / `listener`, everything that alerts | `TELEGRAM_BOT_TOKEN`, `TELEGRAM_CHAT_ID` |
| `matrix.env` | `pos communication matrix sender` / `listener` | `MATRIX_HOMESERVER`, `MATRIX_ACCESS_TOKEN`, `MATRIX_USER_ID`, `MATRIX_ROOM_ID` |
| `scrcpy.env` | `pos communication scrcpy` | `SCRCPY_SERIAL`, `SCRCPY_MAX_SIZE`, `SCRCPY_MAX_FPS`, `SCRCPY_BIT_RATE`, `SCRCPY_FULLSCREEN`, `SCRCPY_RECORD_DIR`, `SCRCPY_PUSH_TARGET`, `SCRCPY_EXTRA_FLAGS` |
| `notify.env` | `lib/notify.sh` (all alerting) | `NOTIFY_PLATFORM` (e.g. `telegram,matrix`) |
| `system.env` | `pos system health`, `pos system backup` | `BACKUP_SERVICE_ROOTS`, `HEALTH_BACKUP_MAX_AGE_DAYS` |
| `compose.env` | `pos docker compose` | `TS_AUTHKEY`, `TZ`, `DNS_SERVER`, `SERVICES_BASE` |
+32
View File
@@ -265,6 +265,7 @@ Subcommands that need input prompt interactively when args are omitted.
| `pos communication telegram listener` | `bin/pos-communication-telegram-listener` | Telegram bot listener: map `/command` → bash commands and run them from chat; interactive editor for the map | Same `telegram.env` (the bot is the owner, `TELEGRAM_CHAT_ID`). Map lives in `~/.config/linux_post_install/telegram_commands.env` (`/cmd=bash command` lines, chmod 600) |
| `pos communication matrix sender send "text"` | `bin/pos-communication-matrix-sender` | Send a text message (plain or `--markdown`) to a Matrix room via the client-server API; also `login` (password → access token) and `test` | Homeserver + room from `~/.config/linux_post_install/matrix.env` (`MATRIX_HOMESERVER`, `MATRIX_ACCESS_TOKEN`, `MATRIX_USER_ID`, `MATRIX_ROOM_ID`, chmod 600, secrets masked by `pos config matrix`). Precedence: `--room` flag > env > config file |
| `pos communication matrix listener` | `bin/pos-communication-matrix-listener` | Matrix listener: map `/command` → bash commands and run them from room messages; interactive editor for the map | Same `matrix.env` (reacts to `MATRIX_USER_ID`'s own messages; watches `MATRIX_ROOM_ID` or all joined rooms). Map lives in `~/.config/linux_post_install/matrix_commands.env` (`/cmd=bash command` lines, chmod 600) |
| `pos communication scrcpy [cmd]` | `bin/pos-communication-scrcpy` | Mirror/control an Android device via scrcpy+adb: `devices`, `record`, `tcpip`, `connect`, `push`, `pull`, `screenshot`, `info` (bare = mirror) | `scrcpy.env` (`SCRCPY_SERIAL`, `SCRCPY_MAX_SIZE`, `SCRCPY_MAX_FPS`, `SCRCPY_BIT_RATE`, `SCRCPY_FULLSCREEN`, `SCRCPY_RECORD_DIR`, `SCRCPY_PUSH_TARGET`, `SCRCPY_EXTRA_FLAGS`) via `pos config scrcpy` |
`pos communication telegram sender` in detail:
@@ -322,6 +323,37 @@ The access token is a secret — it is stored only in `~/.config/linux_post_inst
The daemon long-polls `/sync` (30s timeout, per-sync `since` token, compact filter that drops presence/account_data/device noise and only requests `m.room.message` timeline events). It reacts only to messages **from `MATRIX_USER_ID`** (your own account — resolved via `/account/whoami` if unset); a `MATRIX_ROOM_ID` restricts it to one room, otherwise every joined room is watched. `/` and `!` prefixes both resolve (`!status` = `/status`). `/help` lists mapped commands; an unmapped command replies "Unknown command". Non-command text starting with `ai ` (case-insensitive, e.g. `ai what is Nvidia`) is forwarded to Gemini via `pos ai gemini ask` with a per-room session (`matrix-<room>`; `ai /reset` clears it) and the answer is replied verbatim with markdown stripped. Replies are sent as `m.text` threaded with `m.in_reply_to` on your message. Commands run as your user via `timeout 60 bash -c "…"` (stdout + stderr are replied, truncated to ~3800 chars; empty output → `OK`; non-zero exit is prefixed with `exit <rc>`), so `sudo` inside them needs a NOPASSWD rule. A map value prefixed with `@quiet ` runs the command but does NOT reply — for commands that already send their own notification (e.g. `/status=@quiet pos system health --send`). Map lines may carry a `/cmd::description=…` description. `--enable` warns if linger is off — the service stops when you log out unless you run `sudo loginctl enable-linger $(whoami)`.
`pos communication scrcpy` in detail:
| Command | Behavior |
|---------|----------|
| `pos communication scrcpy` | Mirror the device: opens the scrcpy window (needs a display — over ssh use `ssh -X`). Built from `scrcpy.env` defaults plus any pass-through scrcpy flags (`pos communication scrcpy --turn-screen-off --stay-awake`) |
| `pos communication scrcpy devices` | `adb devices -l` — the source of serials for `SCRCPY_SERIAL` |
| `pos communication scrcpy record [file] [--headless]` | Record a session to an mp4 — default `$SCRCPY_RECORD_DIR/<device>_<date>.mp4`; `--headless` adds `--no-playback` (no window — headless-server friendly) |
| `pos communication scrcpy tcpip [port]` | `adb tcpip <port>` (default 5555) — switch the USB device to wireless adb, prints the reconnect command with the detected device IP |
| `pos communication scrcpy connect <ip[:port]>` | `adb connect` then mirror over WiFi (`-s <ip:port>`) |
| `pos communication scrcpy push <local> [remote]` | `adb push` — default destination `$SCRCPY_PUSH_TARGET` (`/sdcard/Download`, scrcpy's own default) |
| `pos communication scrcpy pull <remote> [local]` | `adb pull` — default local dir is the current directory |
| `pos communication scrcpy screenshot [file]` | `adb exec-out screencap -p` → a PNG, default `$SCRCPY_RECORD_DIR/<device>_<date>.png` |
| `pos communication scrcpy info` | Device model, Android version, SDK, serial (`adb shell getprop`) |
A device must have **USB debugging** enabled (Developer options) and the phone's "allow USB debugging" dialog accepted on first connect. `devices`, `record --headless`, `tcpip`, `connect`, `push`/`pull`, `screenshot`, `info` work without a display; the bare mirror needs one.
**Configuration** (`~/.config/linux_post_install/scrcpy.env`, edit with `pos config scrcpy`):
| Key | Required | Default | Purpose |
|-----|----------|---------|---------|
| `SCRCPY_SERIAL` | no | — | Default device serial/`ip:port` (from `devices`) — passed as `-s` to adb/scrcpy |
| `SCRCPY_MAX_SIZE` | no | — | Limit video size, e.g. `1920` (scrcpy `--max-size`) |
| `SCRCPY_MAX_FPS` | no | — | Limit frame rate, e.g. `60` (scrcpy `--max-fps`) |
| `SCRCPY_BIT_RATE` | no | — | Video bit rate, e.g. `8M` (scrcpy `--video-bit-rate`) |
| `SCRCPY_FULLSCREEN` | no | `false` | `true` adds `--fullscreen` |
| `SCRCPY_RECORD_DIR` | no | `~/Videos/scrcpy` | Output dir for `record`/`screenshot` defaults |
| `SCRCPY_PUSH_TARGET` | no | `/sdcard/Download` | Default `adb push` destination |
| `SCRCPY_EXTRA_FLAGS` | no | — | Extra scrcpy flags appended to every mirror |
Requires `scrcpy` + `adb` (added to `preinstall.sh` PACKAGES). The apt `scrcpy` build is older than the latest release — the optional app `apps/media/scrcpy.sh` installs the current GitHub release (bundles `adb`); run it via `./install.sh --apps` or directly.
### entertainment
**File:** `bin/pos-entertainment-send`
+75 -2
View File
@@ -1,7 +1,8 @@
# How-To: `pos communication`
Messaging and alerts over Telegram and Matrix. Tools: `telegram-sender`,
`telegram-listener`, `matrix-sender`, `matrix-listener`.
Messaging and alerts over Telegram and Matrix, plus Android mirroring. Tools:
`telegram-sender`, `telegram-listener`, `matrix-sender`, `matrix-listener`,
`scrcpy`.
| Tool | What it does |
|------|--------------|
@@ -9,6 +10,7 @@ Messaging and alerts over Telegram and Matrix. Tools: `telegram-sender`,
| `pos communication telegram listener` | Bot listener: map `/command` → bash and run it from chat (systemd user daemon) |
| `pos communication matrix sender` | Send messages to a Matrix room via the client-server API (send, test, login) |
| `pos communication matrix listener` | Matrix listener: map `/command` → bash and run it from room messages (systemd user daemon) |
| `pos communication scrcpy` | Mirror/control an Android device over USB or WiFi (scrcpy+adb) |
`telegram-sender` is the workhorse: it backs the whole **notify system**
health digests, backup alerts, firewall changes — and can be used directly.
@@ -227,6 +229,77 @@ pos communication matrix listener --disable # remove it
---
## `pos communication scrcpy`
Mirror and control an Android device from the PC — the phone's screen in a
window, controlled with mouse + keyboard (scrcpy by Genymobile, no root, no
phone app). Works over USB or WiFi.
### One-time setup
```bash
# phone: Settings → About → tap "Build number" 7× → Developer options → enable
# "USB debugging"; plug it in and accept the "Allow USB debugging" dialog
pos communication scrcpy devices # confirm the phone shows as "device"
pos communication scrcpy info # model / Android version
pos config scrcpy # optional defaults (serial, size, fps, ...)
```
Requires `scrcpy` + `adb` (both in preinstall PACKAGES). The apt build is older
than the latest release — install the current GitHub release (bundles `adb`)
with the optional app `apps/media/scrcpy.sh` (or `./install.sh --apps`).
### Mirror
```bash
pos communication scrcpy # USB device, config defaults
pos communication scrcpy --turn-screen-off # pass any scrcpy flag through
pos communication scrcpy --no-audio --always-on-top
```
The window needs a display — over ssh use `ssh -X` (and a phone already
reachable over WiFi, see below). `scrcpy --help` lists every flag; the wrapper
forwards flags verbatim.
### Wireless (no USB cable)
```bash
pos communication scrcpy tcpip 5555 # switch the USB device to WiFi adb
# unplug the phone, then:
pos communication scrcpy connect 192.168.1.42:5555 # connect + mirror
```
`tcpip` prints the exact `connect` command with the phone's detected IP. Set
`SCRCPY_SERIAL` in `pos config scrcpy` so later bare `pos communication scrcpy`
goes straight to that device.
### Record / screenshot / files
```bash
pos communication scrcpy record --headless # record to ~/Videos/scrcpy/, no window
pos communication scrcpy record clip.mp4 # explicit file
pos communication scrcpy screenshot # PNG to ~/Videos/scrcpy/
pos communication scrcpy push ~/app.apk # → /sdcard/Download/
pos communication scrcpy pull /sdcard/DCIM/Camera ~/photos
```
These all work headless — handy on the homelab box for grabbing a phone's
screen/file without a desktop.
**Troubleshooting:**
- "no device connected" → is USB debugging on, is the "Allow USB debugging"
dialog accepted, and does `pos communication scrcpy devices` show the serial?
- Device shows `offline`/`unauthorized` → re-accept the USB debugging dialog on
the phone (unplug/replug); `adb kill-server` may help.
- "not reachable" after `tcpip` → the phone's WiFi IP changed; re-check with
`adb devices` or run `tcpip` again while plugged in.
- Mirror window is blank / no audio → older apt scrcpy lacks features; install
the latest with the `apps/media/scrcpy.sh` app installer.
- `ssh -X` mirror is slow → prefer WiFi or a wired LAN; bump `SCRCPY_MAX_FPS`
down or set `SCRCPY_BIT_RATE` lower in `pos config scrcpy`.
---
## Related
- Reference + config file details: [DOC/POS.md → communication](../POS.md)