rms-devremote
v3.2.0
Published
Control your terminal remotely from your phone — mobile PWA with push notifications and zero open ports
Maintainers
Readme
rms-devremote
Control your terminal remotely from your phone — with push notifications, a mobile-optimized PWA, and zero open ports.
How it works
Your machine runs a tmux session exposed via a custom xterm.js terminal server (WebSocket + node-pty). A Cloudflare Tunnel secures the connection with no open ports. When Claude Code needs your approval, ntfy sends a push notification to your phone.
Phone (PWA)
|
├─ terminal.your-domain.com ─► Cloudflare Tunnel ─► Terminal Server (port 7681)
| └─► node-pty → tmux session
|
└─ notify.your-domain.com ─► Cloudflare Tunnel ─► ntfy (Docker)
▲
Claude hooks
(Notification / Stop)Mobile PWA Features
- xterm.js v6 terminal with high-contrast OLED dark theme
- Touch toolbar — ← → ↑ ↓ Enter ⌫ Esc Tab Y N ^C
- Scroll mode — tmux copy-mode with progressive acceleration
- Input bar — real-time character forwarding to terminal
- Double-tap = Enter, swipe gestures for navigation
- Info panel — tap "devremote" header to see status, path, uptime
- Disconnect screen — clear feedback when server is unreachable
- PWA installable — add to home screen, works offline (cached assets)
- Orientation support — landscape/portrait auto-resize
Security
- Cloudflare Tunnel — zero open ports, IP hidden, traffic encrypted
- HTTP Basic Auth — credentials required for all routes + WebSocket
- Single client — only one WebSocket connection at a time
Prerequisites
- Docker installed and running
- A Cloudflare account with a domain and a Tunnel token
- tmux installed on your machine
- Node.js 20+ with build tools (
make,gccfor node-pty) - The ntfy app on your phone
Installation
npm install -g rms-devremoteCommands
| Command | Description |
|---|---|
| rms-devremote | Open interactive dashboard |
| rms-devremote setup | First-time setup wizard |
| rms-devremote link | Start tunnel, terminal server, hooks, tmux |
| rms-devremote unlink | Stop everything, remove hooks |
| rms-devremote attach | Attach locally to the tmux session |
| rms-devremote status | Show live status of all services |
| rms-devremote ping | Send a test notification |
| rms-devremote check | Full system health check |
| rms-devremote clean | Interactive cleanup |
Quick start
# 1. First-time setup (run once)
rms-devremote setup
# 2. Link your machine
rms-devremote link
# 3. Open the PWA on your phone
# https://terminal.your-domain.com
# Enter credentials → terminal + toolbar
# 4. Check status anytime
rms-devremote statusArchitecture
rms-devremote/
├── src/
│ ├── index.ts CLI entry point (Commander)
│ ├── commands/
│ │ ├── setup.ts Interactive setup wizard
│ │ ├── link.ts Start tunnel + server + hooks
│ │ ├── unlink.ts Stop tunnel + remove hooks
│ │ ├── attach.ts Local tmux attach
│ │ ├── status.ts Live status dashboard
│ │ ├── ping.ts Send test notification
│ │ ├── check.ts System health check
│ │ ├── clean.ts Interactive cleanup
│ │ ├── dashboard.ts Default no-arg view
│ │ └── battery.ts Battery worker entrypoint
│ ├── server/
│ │ ├── index.ts Express + WebSocket server
│ │ ├── terminal.ts node-pty wrapper (tmux attach)
│ │ ├── auth.ts HTTP Basic Auth middleware
│ │ └── frontend.ts Inline HTML/CSS/JS generator (PWA)
│ ├── services/
│ │ ├── config.ts Config + env file I/O
│ │ ├── docker.ts Docker daemon + container management
│ │ ├── ttyd.ts Terminal server start/stop/pid
│ │ ├── tmux.ts tmux session management
│ │ ├── ntfy.ts ntfy notifications + health
│ │ ├── hooks.ts Claude hooks merge/remove
│ │ ├── battery.ts Battery info + sleep inhibit
│ │ ├── process.ts PID file management
│ │ └── shell.ts Shell helpers
│ └── setup-server/ Setup wizard web UI
├── docker/ Docker Compose stack (tunnel + ntfy)
└── scripts/ Hook scripts (notify.sh)Data directory
All runtime data is stored in ~/.rms-devremote/:
~/.rms-devremote/
├── config.json Domains, ports, battery thresholds
├── .env Secrets (tunnel token, credentials, ntfy password)
├── hooks.json Claude hook definitions
├── pin.hash PIN hash (for future lock screen)
├── inhibit.pid Sleep inhibitor PID
├── battery.pid Battery watcher PID
├── notify.sh Claude notification hook script
├── docker-compose.yml Generated Docker Compose file
└── ntfy/server.yml ntfy server configurationHow notifications work
When Claude Code runs inside the tmux session:
- Notification hook — fires when Claude needs your permission → sends ntfy push
- Stop hook — fires when Claude finishes → sends ntfy push
You receive the notification on your phone, open the PWA, and approve/deny using the toolbar buttons.
Platforms
- Linux — fully supported
- macOS — fully supported (uses
caffeinatefor sleep inhibit) - Windows — WSL2 required
License
MIT
