Blog
Beyond SSH: Why WebSocket Beats Terminal Protocols for AI Coding Agents
SSH was designed for interactive human sessions. AI coding agents need something different. Here's why WebSocket is the better protocol for remote agent control.
Follow product and engineering updates from this channel.
Browse categoryWhen developers first hear about controlling Claude Code from a phone, the natural reaction is: "Why not just SSH into my Mac?"
It's a reasonable question. SSH is proven, secure, ubiquitous. Every developer knows it. There are excellent mobile SSH clients like Termius, Blink Shell, and Prompt. Why build something different?
The answer isn't that SSH is bad. It's that AI coding agents have fundamentally different interaction patterns than interactive shell sessions, and those differences compound into a worse experience when you try to force-fit SSH.
The Interaction Model Mismatch
SSH was designed in 1995 for a specific model: a human sits at a terminal, types commands, reads output, types more commands. The session is interactive and synchronous — you're actively engaged the entire time.
AI coding agents invert this model:
| SSH (Interactive Shell) | AI Agent Control | |
|---|---|---|
| Session duration | Minutes to hours of active use | Hours to days, mostly idle monitoring |
| Human attention | Continuous | Intermittent — check when notified |
| Input pattern | Frequent keystrokes | Occasional prompts + approval decisions |
| Output pattern | Response to your commands | Long autonomous streams you scan, not read |
| Critical events | You see them because you're watching | You might miss them if you're not watching |
| Failure mode | You notice immediately | Agent might wait indefinitely for approval |
The last two rows are the problem. When Claude Code finishes a task or needs your approval for a dangerous operation, SSH has no way to tell you. You have to be watching.
Problem 1: No Push Notifications
This is the biggest gap. With an AI coding agent, the most valuable workflow is:
- Send a task: "Refactor the payment module to use the new API"
- Put your phone away
- Get notified when Claude finishes or needs input
- Review and continue
SSH cannot do step 3. The SSH protocol has no mechanism for pushing notifications to a mobile device. The TCP connection exists only while your SSH client is in the foreground (or using Mosh, while the UDP session is alive). Even then, there's no bridge between "data appeared in the terminal" and "send a push notification to this device."
You can hack around this with shell scripts that send notifications via external services, but that's fragile infrastructure you have to build and maintain yourself.
WebSocket approach: The server monitors Claude Code's output and hook events. When it detects a completion or approval request, it pushes a structured event to connected clients. The iOS app converts these into native push notifications. No polling, no external services.
Problem 2: iOS Background Behavior
iOS aggressively suspends apps that aren't in the foreground. An SSH client that goes to the background gets roughly 30 seconds before iOS suspends its network connections. After that:
- SSH: Connection drops. When you reopen the app, you get a "broken pipe" error. You reconnect, but you've lost your scroll position and any output that happened while you were away.
- Mosh: Better — it uses UDP and can resume. But you still miss everything that happened during suspension. And Mosh doesn't solve the notification problem.
This is a fundamental iOS constraint, not a bug in SSH clients. Apple doesn't allow arbitrary background network connections for battery reasons.
WebSocket approach: The server buffers terminal output regardless of client connection state. When the iOS app returns to the foreground, it reconnects automatically and performs a multi-stage state hydration — refreshing at 0.2s, 0.7s, and 1.5s after reconnecting to capture the full current state. Meanwhile, critical events (task completion, errors) are delivered as push notifications even when the app is suspended.
Problem 3: Session State Management
AI coding agents often run multiple parallel tasks. You might have:
- Session A: refactoring the auth module
- Session B: writing tests for the API layer
- Session C: fixing a production bug
With SSH, managing this means:
- SSH into your Mac
- Manually attach to the right tmux session:
tmux attach -t session-a - Check status, detach:
Ctrl+B, D - Attach to the next session:
tmux attach -t session-b - Repeat
It works, but it's manual and error-prone on a phone keyboard.
WebSocket approach: The server exposes session management as structured commands. The iOS app shows a list of active sessions with their current states. Tap to switch. Create new sessions with a path picker that browses your Mac's filesystem. Kill sessions with a swipe. The server handles all the tmux orchestration.
Problem 4: Agent Event Semantics
SSH transports raw bytes. It doesn't understand what's happening in the terminal. It doesn't know the difference between Claude thinking, Claude writing code, Claude waiting for approval, or Claude finishing a task.
Claude Code has a hook system that fires shell scripts on specific events: task start, task completion, notification events. These hooks are how the server learns about agent state transitions.
SSH limitation: There's no clean way to route these hook events through an SSH session. You'd need a separate channel (another SSH connection, a webhook service, something) running alongside your terminal session.
WebSocket approach: The server receives hook events via HTTP POST from Claude Code's hook scripts. It parses them, deduplicates them (with a 3-second window to avoid duplicate alerts), and pushes them to the iOS app over the same WebSocket connection that carries terminal data. One connection, multiple data types.
Problem 5: Authentication and Access Control
SSH authentication is powerful but complex for mobile use cases:
- Key management on iOS is awkward
- You need to configure sshd on your Mac
- Port forwarding through NAT requires additional setup
- Exposing SSH to the internet demands careful security configuration
WebSocket approach: Tactic Remote uses API key authentication over WebSocket. For LAN connections, the API key is optional (your home network is the trust boundary). For Cloudflare Tunnel connections, the API key is required. The Mac app generates a 32-character random key and transfers it via QR code — no key file management, no sshd configuration.
This is a deliberately simpler security model. It trades SSH's flexibility for ease of setup. If you need the security guarantees of SSH public key authentication, SSH is the right tool — but probably for a different use case.
When SSH Is Still Better
SSH wins when:
- You manage many servers — SSH is the standard protocol for server access. One client, many hosts.
- You need file transfer — SFTP/SCP are built into SSH. Tactic Remote doesn't do file transfer.
- You use non-Claude tools — SSH is agent-agnostic. It works with any terminal application.
- You need port forwarding — SSH tunnels are battle-tested for proxying services.
- Your compliance requirements mandate SSH — some organizations require SSH for audit and access control.
The Architecture in Practice
Here's what the WebSocket architecture looks like for Tactic Remote:
The server sits between the phone and Claude Code, adding:
- Event semantics (raw terminal bytes become structured events)
- Session management (one server, many tmux sessions)
- Reconnection resilience (buffered state, automatic hydration)
- Notification routing (hook events become push notifications)
SSH would give you the raw terminal connection (the top arrows), but none of the intelligence in between.
What About Mosh?
Mosh (Mobile Shell) is the most common suggestion for improving SSH on mobile. It uses UDP instead of TCP, which helps with:
- Network roaming (switching between WiFi and cellular)
- Connection persistence (the server keeps state even when the client disconnects)
- Local echo (instant keystroke feedback regardless of latency)
Mosh genuinely improves the mobile SSH experience. But it still doesn't solve the fundamental issues:
- No push notifications
- No agent event awareness
- No structured session management
- Still subject to iOS background suspension (though recovery is faster)
If you're committed to SSH-based tools, Blink Shell with Mosh is the best iOS option. It's a good tool solving a different problem.
Conclusion
The question isn't "SSH or WebSocket?" as an abstract protocol comparison. It's "what interaction model does your workflow need?"
If you're managing servers and running interactive commands, SSH is the right protocol with decades of proven reliability.
If you're controlling an AI agent that runs autonomously, needs your attention intermittently, and benefits from push notifications and structured event handling, a purpose-built WebSocket architecture solves problems that SSH cannot — not because SSH is flawed, but because it was designed for a different era of human-computer interaction.
Try Tactic Remote
Control your coding Agents from your phone
Connect to Claude Code, Codex, and other Agents on your Mac, Windows, or Linux computer. Check progress and send the next instruction from iPhone or iPad.