Two months ago I was SSH'd into a server from my phone on a train. Switched to another app for 10 seconds, came back — tab killed, session gone.
Every mobile terminal app has the same problem: none can actually keep a connection alive. The OS kills background processes, switches networks, or puts the radio to sleep.
I flipped the model: what if the shell keeps running on a remote agent, and your phone is just the display?
Architecture
- Worker — lightweight agent on any machine. Manages PTY sessions that keep running with zero connected clients.
- Gateway — .NET 10 middleware. Auth, routing, session coordination.
- Client — Web (React + xterm.js), iOS, Android, HarmonyOS. Pure rendering with scrollback replay on reconnect.
Client (Browser / iOS / Android / HarmonyOS)
↕ SignalR
Gateway (.NET 10)
↕ SignalR
Worker (.NET 10 + PTY)
The Hard Part: Hand-Rolling SignalR for HarmonyOS
On iOS/Android/Web, there's a Microsoft SDK. On HarmonyOS? Nothing.
1091 lines of ArkTS later, I had a full SignalR client:
- Negotiate handshake — HTTP POST, extract connection token
- WebSocket transport — exponential backoff reconnection
- Hub protocol — 5 message types (Invocation, StreamItem, Completion, Ping, Close), 0x1E record-separated
- Keepalive — 15s ping, cyclic reconnect (official SDK gives up after 5; mine does 15)
switch (message.type) {
case 1: this.invokeHandler(invocation.target, invocation.arguments); break;
case 2: pending.resolve(streamItem.item); break;
case 3: completion.error ? pending.reject(err) : pending.resolve(result); break;
case 6: break; // Ping
case 7: this.handleCloseMessage(close); break;
}
Virtual Keyboard on Mobile
No physical keyboard means no Ctrl+C. My solution: sticky modifier keys. Tap Ctrl once to latch it, tap C to send SIGINT:
const ch = 'c'.toLowerCase().charCodeAt(0); // 99
this.sendInput(String.fromCharCode(ch - 96)); // x03 = SIGINT
ArkTS Constraints
Every one caused a compile error: no as const, no untyped object literals, no destructuring, throw only accepts Error.
Numbers
425 commits, 53 days, 1 person, 5 platforms. HarmonyOS: 8645 lines ArkTS, 1091 lines SignalR.
Try It
docker run -d -p 5045:5045 ghcr.io/monster-echo/corterm-gateway:latest
GitHub: github.com/monster-echo/CortexTerminal2
App Store · Google Play · Huawei AppGallery
Questions about SignalR, PTY lifecycle, or cross-platform CI? Ask below.
Top comments (0)