UAP Device Control
Cross-platform outbound Device Control client for Universal Agent Platform.
Requirements
- Node.js 24.18.1 or later, 25.x, or 26.x (
>=24.18.1 <27). Prefer supported LTS majors for ongoing installations. - a public UAP Device Control origin for first login
- Windows, Linux or macOS
Runner, WSL, cloudflared, a separately installed Device Agent and an inbound device port are not required for temporary npx mode.
First login
The public npm package does not embed a development, staging or production hostname. Select the intended UAP environment explicitly on first login:
npx @codingfrees/uap-device-control@latest login --origin https://<uap-device-control-origin> --pairing-code <temporary-admin-code>
Open the UAP Device Control /admin console, select the authorized owner or workspace identity, and generate a one-time pairing code (valid for five minutes). The CLI exchanges this code via OAuth PKCE and stores a revocable device-scoped credential for the exact origin; it does not require GitHub/Google login. Later commands reuse the saved origin and credential. To change environments, logout first and then pair with the other origin.
You can also provide the origin through UAP_DEVICE_CONTROL_ORIGIN.
Remote session
npx @codingfrees/uap-device-control@latest remote
The interactive CLI uses concise human-readable status lines by default (✅, ❌, ⚠️, 🔐, 🌐, 🔌, 🔧). Use --json for stable JSONL output in scripts and log collectors. Only one remote process may use a state directory at a time; a new temporary Remote can replace a verified prior temporary instance, while unrelated or service-managed processes fail closed. OAuth refresh is serialized across processes, and access-token renewal is retried in the existing broker session rather than forcing a device reconnect. On relays advertising transport-ping-v1, a bounded 30-second application heartbeat receives automatic responses while the Durable Object hibernates; a missing reply causes the CLI to replace the silent half-open transport. Older relays continue using on-demand presence probes until both sides are updated.
Interactive remote sessions display the UAP Device Control banner at startup; JSON and service modes remain banner-free. Use --debug to add local terminal-command diagnostics containing the executable, redacted argument vector, working directory and shortened request ID. Environment values are never logged, and common credential-bearing flags and headers are redacted.
By default the Remote process also starts the loopback-only semantic browser bridge on port 18700. Until the UAP Browser Extension is paired, the CLI prints a short-lived pairing code. Browser control can be disabled with --no-browser-control or moved to another loopback port with --browser-port <port>.
Existing extensions paired on the former port 8800 retain that port in browser storage. After updating npm Remote and Browser Extension, open Device Control · Browser in extension Settings and use Reconnect browser bridge with port 18700 (or the CLI-reported port). This moves the existing pairing after an explicit user action, rather than silently sending the saved bearer to a new local port or resetting device credentials. Use browser-reset only if pairing authority was lost or the extension was replaced.
If a browser extension was replaced or lost its local token, stop remote, run npx @codingfrees/uap-device-control@latest browser-reset, then start remote again. This resets only the browser pairing and preserves the device identity and login.
By default only the current directory is exposed as a Device Control filesystem root. Additional authority must be explicit:
npx @codingfrees/uap-device-control@latest remote \
--root files=/absolute/path \
--read-only-root archive=/absolute/archive \
--allow-executable /absolute/path/to/executable \
--allow-service example.service
Semantic browser control
Semantic browser control is optional and is executed by the device-control-browser companion assembly inside the generic UAP Browser Extension. It does not require Chrome/Edge remote-debugging flags or CDP.
- Install or enable the optional
device-control-browsercompanion in the workspace; it depends ondevice-controlandbrowser-extension-host. - Start
remoteand note the local🔐 Browser pairing code. - Open the UAP Browser Extension popup and the Device Control · Browser feature.
- Enter the pairing code and bridge port shown by the CLI, then enable browser control.
- The Remote session reconnects automatically and advertises the browser capabilities.
The browser surface supports bounded tab listing, open/navigate/activate/reload/back/forward/close, visible-page snapshot, selector-based click, bounded literal text entry and bounded vertical scrolling. Only HTTPS or loopback HTTP pages are eligible. Page content is untrusted data, no page-supplied JavaScript is evaluated, and every MCP browser tool is approval-gated.
Status
npx @codingfrees/uap-device-control@latest status
status reports the local device identity, authentication state and remote presence when authenticated.
Account identity and switching
Use whoami to inspect the account name, subject and workspace verified by the relay, not inferred from stored token content:
npx @codingfrees/uap-device-control@latest whoami
To move a Windows device from one account to another, stop the current remote process or installed service, then run:
npx @codingfrees/uap-device-control@latest switch-account
npx @codingfrees/uap-device-control@latest whoami
npx @codingfrees/uap-device-control@latest remote
During the OAuth browser step, sign in to the intended account, not the existing browser session. Alternatively, generate a single-use pairing code for the intended user in the Device Control admin console and pass it to switch-account --pairing-code <code>. The device ID and browser pairing state are preserved. The prior refresh credential is revoked after a successful new login; if revocation cannot be confirmed, the CLI displays a warning. A failed new login leaves the old authorization intact. The relay and CLI must both support the identity endpoint to display verified identity; otherwise whoami explicitly reports that verification is unavailable instead of guessing.
Persistent service
After login:
npx @codingfrees/uap-device-control@latest install-service
The same runtime is persisted using the platform adapter (Windows scheduled startup, Linux systemd user service, macOS launchd).
The install-service command refuses to install a second persistent Remote if an installed Runner V2 is detected on Windows or Linux; temporary remote mode remains independent. Service installation stages the runtime atomically and retains a .previous copy for rollback if registration fails. This is not a signed automatic update channel; npm publishing and OS-service updating remain separate lifecycles.
npm client versus ChatGPT MCP
The npm client does not use MCP as its device transport. It needs the public UAP origin for OAuth and the outbound Device Control routes under /device-control/remote/*.
The /mcp endpoint is required by ChatGPT/Codex and the public OpenAI plugin listing. A production deployment may expose both surfaces from the same canonical HTTPS origin, but they are independent protocol paths and use separate OAuth scopes. The npm client uses the isolated device-control:device scope; ordinary MCP read/write tokens are rejected by the remote-device broker.
Security boundary
The client opens only outbound HTTPS connections plus the optional browser bridge bound strictly to 127.0.0.1. Filesystem roots, executable allowlists and service allowlists remain local explicit authority. Device credentials are origin-bound and cannot be silently reused against another environment. Browser pairing uses a short-lived local code, pins the exact extension ID and persists only a token hash on the Remote side; the bearer itself stays in extension storage.
Publishing
Stage a verified dual-use release for npm maintainer approval with:
pnpm publish:public
Validate the exact release without publishing with pnpm publish:public -- --dry-run.
For npm whoami HTTP 401 in Linux/WSL, renew authentication locally using npm login --registry=https://registry.npmjs.org/ --auth-type=web, then confirm npm whoami. Do not paste credentials into issue reports or logs. npm versions are immutable: bump the package version and commit a clean tree before publishing.
The script requires clean package inputs, the persistent contentPolicy declaration and bundled DISCLOSURE, and an unused version. It builds and checks the package, then calls npm stage publish. The root pnpm deploy:npm entrypoint uses the same staging script. A maintainer must inspect and explicitly approve the stage on npmjs.com with 2FA before the version becomes publicly available; the script does not bypass npm identity checks or claim a staged version is published.
UAP Downloads release candidates
The UAP downloadable product candidates workflow also builds the Node 26 portable uap-device-control-remote-<version>.mjs, its SHA-256 and sanitized provenance from the exact candidate source SHA. This executable JavaScript file requires Node.js 26; it is not a signed Windows/macOS native installer and is separate from the existing npm release channel. The private CI artifact is not a public UAP Downloads release. Each approved public release must embed Windows/Linux/macOS download, checksum, login, scoped-root, browser pairing and update/removal instructions in its description; live OS/browser certification and separate publication approval are required.
ChatGPT MCP tool profiles
The connected MCP URL controls which tools are advertised and callable. A device-reported capability alone does not make its corresponding ChatGPT tool available.
| Connection URL | Profile | Relevant tools |
|---|---|---|
https://device-control.aemdpc.ro/mcp | core (default) | Device discovery, health, processes, terminal and approvals |
https://device-control.aemdpc.ro/mcp?profile=browser | browser | list_browser_tabs and paired-browser operations |
https://device-control.aemdpc.ro/mcp?profile=screen | screen | list_monitors, screenshot, streams and desktop controls |
https://device-control.aemdpc.ro/mcp?profile=filesystem | filesystem | Root discovery and filesystem operations |
https://device-control.aemdpc.ro/mcp?profile=marketplace | marketplace | All Device Control MCP tools |
To enable the advanced tools in ChatGPT, connect an explicit browser or screen profile, or the marketplace profile for the complete surface. The plugin packager supports --profile browser, --profile screen, and --profile marketplace, and embeds the matching URL in mcp.json. An existing core connection does not gain advanced tools just because the remote device reports those capabilities.
Profiles restrict both tools/list and tools/call; OAuth scopes and device/workspace authorization still apply. Browser reads require a paired browser extension and elevated-access approval; screenshots require a separate approval. Never grant approval automatically during diagnostic checks.