Squad Remote Control
⚠️ Experimental — Squad is alpha software. APIs, commands, and behavior may change between releases.
Control Copilot CLI from your phone via a secure WebSocket tunnel. Perfect for demos, pairing on mobile, or monitoring runs from anywhere.
squad start --tunnel
# Shows QR code → scan with phone → terminal appears in browser
What It Does
squad start spawns Copilot CLI in a pseudo-terminal (PTY) and mirrors output to your phone in real-time via:
- PTY — Copilot runs in a full interactive terminal
- WebSocket server — Terminal I/O streams live via WebSocket
- devtunnel — Secure public URL with authentication (optional)
- Phone browser — xterm.js terminal renders on your phone
Architecture diagram:
[Copilot CLI in PTY]
↓ (terminal output/input)
[WebSocket Server]
↓ (bidirectional)
[devtunnel] (optional, provides public URL)
↓ (HTTPS + private auth)
[Phone Browser (xterm.js)]
↓ (mobile keyboard shortcuts, replay buffer)
[Your Phone]
Prerequisites
Required
-
devtunnel CLI (for
--tunnelmode)# Windows (winget) winget install Microsoft.devtunnel # macOS (Homebrew) brew install devtunnel # Or via GitHub releases # https://github.com/microsoft/devtunnel/releases -
devtunnel authentication (required before first use)
devtunnel user login # Browser opens → authenticate → success
Optional
- Node.js 18+ (for CLI)
- Modern browser on phone (iOS Safari, Chrome, Firefox)
Usage Examples
Basic: Local PTY Terminal
No tunnel, no phone access — just run Copilot in a PTY:
squad start
# Output: Started PTY terminal (PID: 12345)
# Copilot running locally
With Phone Access (devtunnel + QR)
Create a tunnel, show QR code, let your phone scan and connect:
squad start --tunnel
# Output: Started devtunnel session
# Session ID: abc123xyz
# QR Code: [████████████████]
# URL: https://abc123xyz-dev.devtunnels.ms
#
# Tap or scan QR on your phone → terminal appears
Scan the QR code with your phone camera. Opens browser → terminal renders with xterm.js.
Custom Port
Specify the WebSocket server port:
squad start --port 3456
# Output: WebSocket listening on localhost:3456
# Access via: ws://localhost:3456
Custom Command
Run a different shell or program instead of copilot:
squad start --tunnel --command powershell
squad start --tunnel --command "python"
squad start --tunnel --command "bash -i"
Pass Copilot Flags Through
All flags after --tunnel pass to copilot:
squad start --tunnel --yolo
squad start --tunnel --model gpt-4
squad start --tunnel --no-config
Security Model
Remote access has 7 layers of security:
1. devtunnel Private Auth
- URL requires
Authorizationheader (devtunnel access token) - Tunnel is private by default — no public discovery
2. Session Token (UUID, 4-hour TTL)
- Each session gets a unique token, valid for 4 hours
- Token embedded in QR code or shown as connection string
- Expires automatically
3. Ticket-Based WebSocket Auth
- First request exchanges session token for single-use ticket
- Ticket valid 60 seconds, single use only
- Prevents token replay attacks
4. HTTP Rate Limiting
- 30 requests per minute per IP address
- Blocks brute-force connection attempts
- Rate limit resets hourly
5. Environment Variable Blocklist
- 27 common secret patterns redacted from output
- Blocks:
PASSWORD,TOKEN,SECRET,KEY,AWS_,GITHUB_,API_KEY, etc. - ANSI escape sequences cannot bypass redaction
6. Secret Redaction (27 Patterns + ANSI Bypass Prevention)
- Secrets matching patterns replaced with
[REDACTED] - ANSI codes cannot hide redaction logic
- Example:
Password=mysecret123→Password=[REDACTED]
7. Connection Limits
- Global: Max 5 concurrent phone connections per session
- Per IP: Max 2 concurrent connections per IP address
- Excess connections rejected with 429 (Too Many Requests)
Mobile Keyboard
When your phone connects, a key bar appears below the terminal:
| Key | Action |
|---|---|
| ↑ / ↓ | Scroll history / scroll terminal output |
| ← / → | Move cursor left / right |
| Tab | Insert tab character (or autocomplete if supported) |
| Enter | Send command / newline |
| Esc | Send Escape key (menu mode, cancel) |
| Ctrl+C | Send interrupt signal (SIGINT) — kills running command |
| Space | Insert space |
| ⌫ | Backspace / delete |
Replay Buffer
When a new phone joins the session:
- Terminal history is replayed — joins don’t see a blank screen
- Replay window — last 1000 lines of terminal output
- Scrollback included — can scroll to see previous commands
This means late-joiners see context, not blank canvas.
Session Dashboard
List and manage active devtunnel sessions:
squad start --list-sessions
# Output:
# Session 1: abc123xyz (2 phones connected, 1h 23m running)
# Session 2: def456uvw (0 phones, 2m running)
# Session 3: ghi789rst (1 phone, idle)
Kill a session:
squad start --kill-session abc123xyz
# Output: Session closed. Remaining: 2
Architecture Notes
PTY-Only Mode
Remote Control runs in PTY-only mode — no Copilot ACP (Agent Control Protocol) messages flow through the WebSocket. The terminal is a mirror, not a command channel:
- Terminal I/O (text, control codes) ↔ WebSocket
- ACP protocol stays local to the Copilot process
- No agent instructions flow through the tunnel
This design keeps the tunnel stateless and reduces surface area.
Audit Logging
All connections, authentication, and security events are logged:
~/.cli-tunnel/audit/squad-audit-2025-01-15.jsonl
Each line is a JSON object:
{
"timestamp": "2025-01-15T10:23:45.123Z",
"event": "connection",
"session_id": "abc123xyz",
"phone_ip": "203.0.113.42",
"status": "authenticated"
}
Events logged:
connection— Phone connecteddisconnection— Phone disconnectedauth_failure— Token/ticket validation failedrate_limit— Rate limit exceededredaction— Secret pattern matched and redactedcommand— Command executed (summary, no args)
Rotate daily, keep 30 days by default.
Troubleshooting
”devtunnel not found”
Install devtunnel:
winget install Microsoft.devtunnel
Or check PATH:
where devtunnel
# Should show path to executable
“Not authenticated to devtunnel”
Log in:
devtunnel user login
Phone doesn’t connect (QR code error)
- Check QR code isn’t expired (valid for 5 minutes)
- Verify phone is on same network or has internet
- Try manual URL instead of QR:
# Copy URL from terminal and paste in phone browser https://abc123xyz-dev.devtunnels.ms
Terminal freezes
This is typically Copilot waiting for input. Type a command or press Enter:
squad > [CURSOR BLINKING]
Press Enter to see the prompt.
Audit logs missing
Ensure ~/.cli-tunnel/ directory exists:
mkdir -p ~/.cli-tunnel/audit
Logs are created on first event.
See Also
- CLI Reference — All commands
- Getting Started — Squad setup
- VS Code Integration — Remote Control in VS Code