@beeos-ai/cli
v1.2.6
Published
BeeOS CLI — run AI agents from your desktop
Readme
@beeos-ai/cli
BeeOS Desktop CLI — run AI agents from your terminal.
Install
# Run directly (no install required)
npx @beeos-ai/cli device attach
# Or install globally
npm install -g @beeos-ai/cliPure JavaScript — runs on any platform with Node.js 18+. No native compilation needed.
What's new in 1.1.0
- Multi-OS desktop streaming for the OpenClaw agent: macOS Screen
Sharing, Linux TigerVNC and Windows TightVNC are now first-class
cold-start targets.
beeos initconfigures the host's VNC password, generates~/.beeos/vnc.password, and stages avnc-bridgesidecar in one shot. beeos device attach --self(experimental) — tags the persistedDeviceEntry.backendwith the host's native backend (macos/linux/windows) instead of the historicaladb. Forward- compatible with the upcoming Phase-4 self-attach lifecycle.BEEOS_NO_DESKTOP=1opt-out — single chokepoint at the desktop pipeline. When set, no probe, no cold-start, no UAC / osascript prompt, no TightVNC / TigerVNC / Screen Sharing detection. Useful for CI runners and headless servers.- Linux fleet auto-enable prompt is now offered on Linux too (was darwin-only).
Commands
Device agent (Android)
# Attach a USB-connected Android device as an AI agent (launches
# device-agent + device-mcp-server + scrcpy-bridge in parallel —
# the latter powers WebRTC video / control)
beeos device attach
# Attach a specific device
beeos device attach --serial SERIAL_NUMBER
# Attach all connected devices
beeos device attach --all
# Skip the scrcpy-bridge sidecar; run only device-agent + MCP server
# (useful for iterating on tools / ACP without the video stream)
beeos device attach --no-video
# Attach the host machine itself (experimental, multi-OS) — tags the
# persisted backend as macos / linux / windows depending on the host
beeos device attach --self
# List attached devices
beeos device list --local
# Detach a device (stops every sibling process spawned for that device)
beeos device detach --serial SERIAL_NUMBER
# Send a command to a device
beeos device exec "open Chrome"
# Run a one-shot local task without binding the phone to BeeOS
beeos device run "open Chrome" --serial SERIAL_NUMBER
# Select observation/execution modes and save a trace bundle
beeos device run "open Settings, inspect Display, then return home" \
--serial SERIAL_NUMBER \
--model MODEL_NAME \
--base-url https://api.example.com/v1 \
--observation-mode vision \
--execution-mode advanced \
--output-dir ./device-runs
# Prefer the environment for secrets instead of shell history
OPENAI_API_KEY=YOUR_KEY beeos device run "open Chrome" --serial SERIAL_NUMBER
# Upgrade device-agent + device-mcp-server to latest version
beeos device upgradedevice exec sends a prompt to the persistent agent created by device
attach. device run is an independent local runner: it reuses the fleet MCP
endpoint when available, or starts a temporary ADB MCP server when the phone
has not been attached to BeeOS. The temporary server is stopped when the task
finishes or is interrupted.
BeeRunner local agent
beeos runner ... is a transparent entry point for the independently released
@beeos-ai/runner-agent. The package is downloaded only on first use into
~/.beeos/tools/runner-agent; normal beeos installation stays small and does
not require a global npm install. It controls BeeRunner directly over USB ADB
and does not require QR binding or a BeeOS cloud connection.
# Diagnose and observe the phone
beeos runner doctor --serial SERIAL_NUMBER
beeos runner screenshot --serial SERIAL_NUMBER --output ./screen.png
beeos runner ui --serial SERIAL_NUMBER
beeos runner apps --serial SERIAL_NUMBER
# Act through BeeRunner's AccessibilityService
beeos runner tap 500 800 --serial SERIAL_NUMBER
beeos runner type "hello" --serial SERIAL_NUMBER
beeos runner open-app com.tencent.mm --serial SERIAL_NUMBER
beeos runner back --serial SERIAL_NUMBER
# Run a local natural-language Agent task
beeos runner run "打开微信" --serial SERIAL_NUMBER \
--base-url "$OPENAI_BASE_URL" \
--api-key "$OPENAI_API_KEY" \
--model "$OPENAI_MODEL"Android must show the ADB transport as authorized. UI actions require
BeeRunner to be enabled in Accessibility settings. Screenshots require either
that accessibility service on Android 11+ or an active MediaProjection grant.
When multiple BeeRunner phones are connected, pass --serial. Set
BEEOS_RUNNER_AGENT_VERSION to pin the lazily installed package, or
BEEOS_RUNNER_AGENT_BIN to test a locally built binary.
What attach does
Under the hood beeos device attach orchestrates three sibling
processes for each Android device:
- device-agent (TypeScript, Node 20 —
@beeos-ai/device-agent) — Plan-Act-Reflect agent loop, ACP chat, and orchestration. Binds the phone to your BeeOS account and writes identity to~/.beeos/identity/device-<serial>.key.json. - device-mcp-server (TypeScript, Node 20 —
@beeos-ai/device-mcp-server) — Fastify HTTP MCP server backingscreenshot/tap/swipe/install_apk/execute_commandand ~14 more tools. The agent talks to it on a private loopback port allocated per device (default range starts at127.0.0.1:7900). - scrcpy-bridge (Rust, WebRTC) — mirrors screen + audio and
forwards touch / key input. Shares the same
.key.jsonidentity file the agent uses, and authenticates to EMQX via Agent Gateway's/api/v1/device/bootstrapendpoint — no static MQTT tokens.
The three processes are independent — one crashing does not take down
the others. All three are tracked in ~/.beeos/devices.json; detach
and list operate on the trio atomically. If device-agent /
device-mcp-server aren't yet installed, the CLI runs
npm i -g @beeos-ai/device-agent @beeos-ai/device-mcp-server on first
use. If the scrcpy-bridge binary is missing, it is downloaded on first
attach from GitHub Releases into ~/.beeos/bin/. Override paths via
BEEOS_DEVICE_AGENT_BIN, BEEOS_SCRCPY_BRIDGE_BIN, etc.
When running against a local dev control plane (e.g. api_url =
http://localhost:9080), the CLI automatically points the bridge at
http://localhost:8083 unless platform.agent_gateway_url is
explicitly set to something non-default. Set
BEEOS_AGENT_GATEWAY_URL to override for one-off experiments without
touching config.toml.
OpenClaw agent (local AI assistant)
# Download, install and start an OpenClaw agent
beeos start openclaw
# Stop a running agent
beeos stop openclaw
# Check agent status
beeos status
# Update to the latest version
beeos update openclawMulti-OS desktop streaming
Starting in 1.1.0, beeos init (and beeos start openclaw) drives a
host-aware desktop cold-start so the BeeOS dashboard's desktop view
works on all three major operating systems:
| OS | What gets configured | Auth dialog |
| ------- | --------------------------------------------------------------------------------------------------- | ---------------------- |
| macOS | com.apple.screensharing enabled; ARD_AllLocalUsers=NO; VNC password written to plist + ~/.beeos/vnc.password | osascript admin prompt |
| Linux | ~/.vnc/passwd generated via tigervncpasswd -f; vncserver :1 -localhost yes started; mirrored to ~/.beeos/vnc.password | none (no sudo) |
| Windows | TightVNC registry password (REG_BINARY DES) + LoopbackOnly=1; tvnserver restarted; mirrored to ~/.beeos/vnc.password | UAC consent dialog |
The flow is idempotent: re-running beeos init on an
already-configured host is a no-op. If the cold-start can't run (no
TigerVNC on Linux, no TightVNC on Windows, user declined the prompt,
…) the bind still succeeds and OpenClaw works headlessly — only the
dashboard's desktop view is unavailable.
To opt out entirely, set BEEOS_NO_DESKTOP=1 before running
beeos init. The desktop pipeline returns null at its single
chokepoint (getDesktopPipeline()), so no probe, no prompt, no
cold-start fires. Useful for CI runners and pure headless servers.
Requirements
- Node.js 18+
- Android devices:
adb(Android Debug Bridge) on PATH (the CLI can install Google's official platform-tools on first use) - device-agent + device-mcp-server: TypeScript / Node 20+. The
CLI lazy-installs
@beeos-ai/device-agentand@beeos-ai/device-mcp-serveron firstdevice attach(~20 MB one-time download). No Python required. - scrcpy-bridge (video streaming): auto-downloaded from GitHub
Releases on first
device attach. Supported targets: darwin arm64/x64, linux arm64/x64, windows x64/arm64. On unsupported platforms attach still succeeds — only video is skipped. - Desktop streaming (optional, OpenClaw): a VNC server on the
host. macOS ships Screen Sharing built-in; Linux needs
apt install tigervnc-standalone-server(ordnf install tigervnc-server/pacman -S tigervnc); Windows needswinget install GlavSoft.TightVNC.
Configuration
Config is stored at ~/.beeos/config.toml:
[platform]
api_url = "https://api.beeos.ai"
agent_gateway_url = "https://agent-gw.beeos.ai"
bridge_url = "wss://bridge-sg.beeos.ai"
dashboard_base_url = "https://beeos.ai"
[device]
http_enabled = true
http_port = 9090agent_gateway_url is consumed by the scrcpy-bridge / vnc-bridge
sidecars for bootstrap (Ed25519-signed /api/v1/device/bootstrap
calls). Set it alongside api_url when pointing at a non-default
control plane.
Environment variable overrides
| Var | Effect |
| ---------------------------------- | --------------------------------------------------------------------------------------- |
| BEEOS_NO_DESKTOP=1 | Skip every desktop-streaming codepath. Honoured at getDesktopPipeline() and forwarded by install.sh / install.ps1. |
| BEEOS_VNC_PASSWORD | Per-shell override for the VNC viewer password. Tried before ~/.beeos/vnc.password. |
| BEEOS_AGENT_GATEWAY_URL | Override the Agent Gateway URL without editing config.toml. |
| BEEOS_DEVICE_AGENT_BIN | Absolute path to a pre-installed device-agent binary / JS entry. |
| BEEOS_SCRCPY_BRIDGE_BIN | Absolute path to a pre-built scrcpy-bridge binary. |
| BEEOS_VNC_BRIDGE_BIN | Absolute path to a pre-built vnc-bridge binary. |
| BEEOS_*_RELEASE_URL | Mirror URL for the matching cargo-dist sidecar (corporate proxies / staging). |
| BEEOS_NO_FLEET_AUTOSTART=1 | Suppress the interactive device-agent fleet enable prompt on macOS / Linux. |
| BEEOS_INSTALL_DRY_RUN=1 | Used by install.sh / install.ps1 smoke tests; exits before any state mutation. |
Troubleshooting
Video stays black / "Reconnecting..." in the viewer
scrcpy-bridge uses str0m for WebRTC, which cannot parse Chrome's
mDNS-hidden ICE candidates (xxx.local). In most cases the bridge
recovers automatically via peer-reflexive candidate learning from the
browser's outgoing STUN binding, so you should still see video.
If the browser is in a network where outbound UDP to the bridge's advertised LAN IPs is blocked, the peer-reflexive fallback won't fire and the viewer will keep reconnecting. Two common workarounds while debugging locally:
- Disable Chrome's mDNS hiding for the dev session:
open
chrome://flags/#enable-webrtc-hide-local-ips-with-mdns, set it to Disabled, and restart Chrome. Chrome will then advertise real LAN IPs directly. - Make sure a reachable TURN server is configured on the Runtime
(
TURN_URLS,TURN_USERNAME,TURN_CREDENTIAL). The viewer'siceServersare sourced from thestream-urlAPI and drive the browser's srflx/relay candidate gathering.
In production, we rely on the TURN relay path; the mDNS issue is only a concern when running Chrome + scrcpy-bridge on the same host behind restrictive local firewalls.
Desktop view stuck / black for OpenClaw
Run beeos doctor — it surfaces per-OS hints (TCC permission on
macOS, ~/.vnc/xstartup on Linux, Get-Service tvnserver on
Windows) when the local vnc-bridge-openclaw service is unhealthy.
