DEV Community

wilsen_deng
wilsen_deng

Posted on

Why We Built a Rust Terminal Engine to Babysit Claude Code and Codex on Mobile

Like many developers riding the wave of "vibe-coding", our daily workflow shifted dramatically over the past year. We went from writing code line by line to directing autonomous CLI agents — Claude Code, OpenAI Codex, OpenCode, Aider, and custom harnesses.

These agents usually run on beefy remote machines: an M-series Mac Studio under the desk, a high-core Linux homelab box, or a cloud dev instance.

And that created an unexpected new bottleneck: Babysitting.

You give Claude a task: "Refactor the auth middleware to support WebAuthn, update the integration test suite, and verify all 48 test suites pass."
Then Claude gets to work. It takes 15 minutes. It reads 30 files. It runs cargo test.

Do you sit at your desk staring at the cursor for 15 minutes? Of course not. You get up, walk the dog, grab a coffee, or step onto the subway.

And that’s where the mobile experience completely falls apart.


The Three Silent Killers of Mobile Agent Monitoring

We tried using standard mobile SSH apps. Within 48 hours, the frustrations were unbearable:

1. The Fragile TCP Socket Trap

Standard SSH relies on persistent TCP connections. The moment your phone locks, goes to sleep, switches from Wi-Fi to cellular, or hits an elevator: Connection dropped. Your active session disappears.

2. The Touch-Typing Nightmare

When you unlock your phone, reconnect, and want to resume where you left off, you have to type on a terrible glass virtual keyboard:

claude --resume 7f8a9b-c891-4d32-bb91-0123456789ab
Enter fullscreen mode Exit fullscreen mode

Finding that session ID from history on a 6-inch screen is painful. Doing it three times a day makes you want to throw your phone out the window.

3. The Webview Thermal Meltdown

When Claude runs a test suite and dumps a 10MB compiler error log or diff into stdout, traditional mobile terminals (often running JavaScript/xterm.js inside an embedded Webview or Flutter canvas) completely choke. The UI freezes for 8 seconds, the phone turns into a pocket warmer, and 15% of your battery vanishes in minutes.


Engineering Moku: A Different Approach

We realized we didn't just need "another SSH client". We needed a dedicated cockpit for the Vibe-Coding era.

So we built Moku (portholelab.com/moku). Here is how we tackled the engineering challenges:

1. Agentless Workspace Auto-Discovery

Instead of asking users to install yet another proprietary daemon, background agent, or cloud proxy on their servers, we looked at how modern CLI agents work.

Claude Code, OpenAI Codex, OpenCode, Qoder, Kimi, and Grok CLI all leave structured traces on the host machine:

  • SQLite databases in ~/.claude/projects/
  • JSON/JSONL session logs in ~/.codex/sessions/
  • Standard project root descriptors

Over a single, standard SSH channel, Moku scans these directories, discovers all active and past sessions across your projects, and displays them as visual interactive cards.

Tap a card → Moku re-enters the exact session context in an interactive terminal. Zero typing.

2. Why We Replaced the Terminal Engine with Rust

To eliminate the lag when agents vomit massive logs, we stripped out the legacy Flutter/Dart terminal parser and rewrote the entire terminal core in Rust:

  • Custom ANSI State Machine: Direct byte-stream parsing compiled to native ARM64/x86 assembly.
  • packedRowsV2 Zero-Copy Surface: A compact memory layout that transmits bounded render diffs to the Flutter UI layer rather than re-rendering millions of offscreen cells.
  • Sub-Millisecond Scrollback: Pruning up to 813 million lines/sec with zero stutter.

Here are the real benchmark numbers from our test harness:

Workload Custom Rust Core Flutter AOT Baseline Speedup
ANSI Parser Throughput 28.07 MB/s 13.39 MB/s 2.10×
10 MiB Burst Output 34.96 MB/s 11.21 MB/s 3.12×
Scrollback Append 408.79k lines/s 171.09k lines/s 2.39×
Scrollback Trim 813.59M lines/s 70.53M lines/s 11.54×

A 10MB trace that used to lock up the app now flashes past in ~0.3 seconds.

3. Native Mosh Roaming + Built-in WireGuard (Tailcat)

To kill the connection-drop problem:

  • We embedded native Mosh (Mobile Shell) UDP synchronization directly into the client. Walk out of your home Wi-Fi into 5G? Step into an elevator? Your terminal session stays alive and seamless.
  • No public IP on your remote machine? We integrated Tailcat, an in-app userspace WireGuard mesh transport. Run tailcat --serve=22 on your devbox, paste the token into Moku, and connect peer-to-peer with zero port forwarding and zero root privileges.

4. Live Activity, Dynamic Island & Soot (煤球)

You shouldn't even have to open the app to know if your agent is done:

  • We wired terminal OSC/ANSI escape notifications directly into iOS Live Activities & Dynamic Island.
  • Glance at your phone: see if Claude is Thinking..., Blocked on input, or Completed.
  • And living on the terminal perch is Soot (煤球) — a param-driven pixel mascot that watches over your build, reacts when tests pass, and keeps you company during late-night deploys.

Privacy by Construction: 100% Local-First

We don't want your keys, and we don't want your data:

  • Zero Cloud Middlemen: Your SSH keys and host configurations are stored exclusively on your device using OS-level secure enclaves.
  • Direct P2P: Connections go straight from your phone to your host. No telemetry on your shell streams.

The 10,000 Stars Open-Source Pledge 🌟

Moku is currently free to download and use. But our goal is bigger:

We have pledged on our GitHub repository to fully open-source the entire client and Rust terminal engine once we hit 10,000 GitHub Stars!

If you're building with Claude Code, Codex, or remote agents, we would love for you to try it:

What CLI agents are you currently using in your day-to-day work? We'd love to hear your thoughts and feedback below!

Top comments (0)