English | 简体中文
An unofficial, self-hosted mobile workspace for macOS. It runs the real Shell, tmux, ttyd, Claude Code, and Codex CLI on your Mac, then brings project selection, live output, and terminal interaction to a mobile browser.
This project is a remote command execution gateway, not an ordinary website. Any client that can reach it may be able to read files, run commands, and use CLI sessions already authenticated as the macOS user running the service.
- Both services bind to
127.0.0.1by default and are not directly exposed to the LAN or Internet. - Tailscale Serve inside a controlled tailnet is the recommended access method.
- Do not use Tailscale Funnel or map either service directly to a public port.
- The project currently has no application-level login. Tailscale device identity and Grants/ACLs are the default access boundary.
- Discover and select project directories on the Mac from a mobile browser.
- Switch between Shell, Claude Code, and Codex conversation modes.
- View the active Claude permission mode and switch among Manual, Accept Edits, Plan, and Auto by clicking the mode control or pressing
Shift+Tab. - Stream output through SSE and reconnect to a running task after a short network interruption or after the phone returns from the background.
- Keep Claude sessions and chat history isolated by project.
- Embed a native ttyd terminal with
Esc,Tab,Shift+Tab,Ctrl+C, arrow keys, and clear-screen controls. - Preserve project terminals with tmux and start services automatically with a macOS LaunchAgent.
flowchart LR
iPhone[Mobile browser] --> TS[Tailscale Serve HTTPS]
TS --> Web[H5 and Node API]
TS --> TTYD[ttyd]
Web --> TMUX[tmux project windows]
TTYD --> TMUX
Web --> Claude[Claude Code CLI]
Web --> Codex[Codex CLI]
TMUX --> Shell[macOS Shell and project files]
Remote Shell Mobile does not store Claude or Codex passwords and does not replace the official login flow. Commands run through CLI tools already installed and authenticated on the Mac, under the current macOS user. Usage limits and terms remain those of the corresponding provider.
- macOS
- Node.js
22.13.0or newer tmuxttyd- Tailscale, recommended for remote access
- Claude Code and/or Codex CLI, depending on which modes you want to use
The project does not install system tools automatically. Verify the commands you intend to use first:
node --version
tmux -V
ttyd --version
claude --version # optional
codex --version # optionalgit clone https://github.com/mxx1111/remote-code-mobile.git
cd remote-code-mobile
npm ci
cp .env.example .env.localEdit .env.local and, at minimum, confirm the project root:
REMOTE_SHELL_PROJECTS_ROOT="/Users/your-name/Projects"
REMOTE_SHELL_MACHINE_NAME="My Mac"Build the web app and install the per-user LaunchAgents:
npm run build
./scripts/install-launch-agents.zshThe installer generates plist files using the actual repository path, so the repository can live anywhere. Logs and default session state are stored in .runtime/; set REMOTE_SHELL_STATE_ROOT if you prefer a location outside the repository.
Keep both bind addresses set to 127.0.0.1 in .env.local, then expose two HTTPS endpoints inside your tailnet:
tailscale serve --bg http://127.0.0.1:3001
tailscale serve --bg --https=7681 http://127.0.0.1:7681
tailscale serve statusJoin the phone to the same tailnet and open the https://<machine>.<tailnet>.ts.net/ URL shown by the first command. The embedded terminal uses HTTPS port 7681 on the same host.
If either port is already used by another Serve rule, inspect tailscale serve status before changing anything. When remote access fails, check the Tailscale device state, MagicDNS, and both service ports separately.
After the HTTPS address works, open it in Safari, tap Share, choose Add to Home Screen, enable Open as Web App, and tap Add. The installed web app uses its own icon and standalone window without Safari browser chrome.
A one-time install hint is shown on iPhone when the page is opened in a browser. The service worker caches only the H5 shell and static assets; /api, Claude, Shell, SSE, and terminal traffic always connect directly to the Mac.
Only on a fully trusted LAN, you may explicitly change .env.local to:
REMOTE_SHELL_HOST=0.0.0.0
REMOTE_SHELL_TTYD_HOST=0.0.0.0Restart both services after changing the bind addresses:
launchctl kickstart -k gui/$(id -u)/dev.remote-shell-mobile.server
launchctl kickstart -k gui/$(id -u)/dev.remote-shell-mobile.ttydThis does not add authentication and must never be used for direct Internet exposure.
| Variable | Default | Description |
|---|---|---|
REMOTE_SHELL_PROJECTS_ROOT |
Parent directory of the repository | Directory whose immediate child folders can be selected as projects |
REMOTE_SHELL_MACHINE_NAME |
Current Mac hostname | Device name displayed in the UI |
REMOTE_SHELL_HOST |
127.0.0.1 |
H5/API bind address |
REMOTE_SHELL_PORT |
3001 |
H5/API port |
REMOTE_SHELL_TTYD_HOST |
127.0.0.1 |
ttyd bind address |
REMOTE_SHELL_TTYD_PORT |
7681 |
Local ttyd port |
REMOTE_SHELL_TTYD_PUBLIC_PORT |
7681 |
Port the browser uses to reach the terminal |
REMOTE_SHELL_STATE_ROOT |
.runtime inside the repository |
Session, task, and log directory |
REMOTE_SHELL_WORKSPACE_SESSION |
remote-shell-mobile |
tmux workspace name |
REMOTE_SHELL_TTYD_CREDENTIAL |
Empty | Optional ttyd Basic Auth in user:password format |
If a command is not available on PATH, configure an absolute path with REMOTE_SHELL_NODE, REMOTE_SHELL_TMUX, REMOTE_SHELL_TTYD, REMOTE_SHELL_CLAUDE, or REMOTE_SHELL_CODEX.
Run the local API and Vite development server in separate terminals:
npm start
npm run devBefore submitting a change, run:
npm run check
npm audit --omit=devAfter updating the source, reinstall dependencies, rebuild, and restart the services:
npm ci
npm run build
launchctl kickstart -k gui/$(id -u)/dev.remote-shell-mobile.server
launchctl kickstart -k gui/$(id -u)/dev.remote-shell-mobile.ttydTo remove the persistent services:
./scripts/uninstall-launch-agents.zshThe uninstall script does not delete .runtime or a custom state directory.
.env.local,.runtime/, logs, and model-session files are ignored by Git.- Claude chat history is stored locally in
.runtime/claude-conversations.jsonby default and is not uploaded to a server operated by this project. - The project catalog API returns project names, branches, and display paths to a connected browser, so access control must exist in front of the page.
- Shell, Claude, and Codex child processes inherit the environment and file permissions of the service user.
- The H5 interface does not expose
bypassPermissions, and the backend rejects it. The native terminal still follows the permission configuration of Claude Code itself.
See SECURITY.md for the security policy and docs/ROADMAP.md for planned work.
Remote Shell Mobile is a community project and is not affiliated with or endorsed by Anthropic, OpenAI, Tailscale, or ttyd. Claude, Claude Code, Codex, Tailscale, and other names belong to their respective owners.