Back to Articles

Using Your Mac as a Remote Endless Working Agent with Moshi

The complete guide to setting up a Mac as an always-on AI agent server—nothing to install on your daily driver

Using Your Mac as a Remote Endless Working Agent with Moshi

Using Your Mac as a Remote Endless Working Agent with Moshi

The complete guide to running an always-on AI agent on your Mac and controlling it from your iPhone


TL;DR: Set up your Mac with mosh + tmux. Connect from your iPhone with Moshi. Get push notifications when your agent needs input, approve from anywhere, keep coding.


The Setup

Your Mac sits on your desk running an AI agent in a tmux session. When you step away, the agent keeps working. When it needs input, you get a push notification on your iPhone. Tap to connect with Moshi, approve the action, and walk away.

  • Your Mac: Runs mosh + tmux + claude. Agent runs 24/7.
  • Your iPhone: Moshi handles everything—mosh protocol, push notifications, voice input.
┌──────────────────┐
│   Mac (Desktop)  │  mosh + tmux + claude
│   Always On      │  Agent runs 24/7
└────────┬─────────┘
         │ Push notification
         ▼
┌──────────────────┐
│     iPhone       │  Moshi app
│                  │  Approve & continue
└──────────────────┘

Why Mosh over Plain SSH

SSH over unreliable networks is painful. Switch WiFi networks, go to cellular, or let your phone sleep—your session dies.

Mosh (Mobile Shell) was built for this.

mosh vs SSH

FeatureSSHmosh
ProtocolTCPUDP
Network roamingSession diesSurvives
Packet loss handlingFreezesGraceful
Local echoNoneInstant (~5ms)
Ctrl+C reliabilityCan failAlways works

According to the mosh research paper, on a link with 29% packet loss, mosh reduced average response time from 16.8 seconds to 0.33 seconds—a 50x improvement.

This is critical for "endless" sessions. Your agent might run for hours or days. Mosh keeps you connected across network changes, sleep cycles, and spotty cellular.

The Scrollback Problem

Critical: mosh has no scrollback buffer.

From GitHub issue #122:

"Mosh's terminal scrollback buffer is incomplete because Mosh synchronizes only the visible state of the terminal."

Run ls -la on a large directory, and the overflow is gone. You can't scroll up.

The solution: always use mosh with a terminal multiplexer. Mosh handles the connection. tmux (or Zellij) handles the scrollback.


Mac Setup (Always-On)

Your Mac needs to stay awake and accessible. Here's the configuration.

Prevent Sleep

System Settings → Energy Saver (or Battery → Options on laptops):

  • Prevent automatic sleeping when the display is off: Enable
  • Wake for network access: Enable
  • Start up automatically after a power failure: Enable (if available)

For headless Mac Minis, you can also disable display sleep entirely since there's no display.

Temporary Override with caffeinate

For one-off long sessions without changing system settings:

# Prevent sleep indefinitely (Ctrl+C to stop)
caffeinate

# Prevent sleep for 4 hours
caffeinate -t 14400

# Prevent sleep while a command runs
caffeinate -s claude

Enable Remote Login

System Settings → General → Sharing → Remote Login: Enable

This enables the SSH server. Mosh uses SSH for initial authentication, then switches to UDP.

Install mosh and tmux

# Install Homebrew if needed
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Install mosh and tmux
brew install mosh tmux

Headless Mac Mini Tips

If you're running a Mac Mini without a display:

  1. HDMI dummy plug: Some Macs throttle GPU without a display. A $10 dummy plug fixes this.
  2. Screen Sharing: Enable in System Settings → Sharing for emergency GUI access.
  3. Automatic login: System Settings → Users & Groups → Login Options → Automatic login (use with caution, ensure disk encryption is on).

Terminal Multiplexer: tmux (Recommended)

tmux creates persistent terminal sessions that survive disconnections—essential for remote development.

Why tmux with mosh

  1. Persistence: Sessions survive network drops, phone sleep, and app switches
  2. Scrollback: Captures all output that mosh discards
  3. Multiplexing: Multiple windows and panes in one session
  4. Detach/attach: Start work on your laptop, continue on your phone
  5. Title propagation: Configurable titles that Moshi displays

Recommended Configuration

Create ~/.tmux.conf:

# Large scrollback buffer (default is 2000)
set -g history-limit 50000

# Enable mouse support (scrolling)
set -g mouse on

# Pass window titles to terminal (Moshi displays these)
set -g set-titles on
set -g set-titles-string "#S:#W"

# Reload config
bind r source-file ~/.tmux.conf \; display "Config reloaded"

Apply changes:

tmux source-file ~/.tmux.conf

tmux Cheatsheet

All commands use the default prefix Ctrl+B. Moshi has a dedicated Ctrl+B button and a tmux shortcuts panel for easy access.

Sessions:

CommandDescription
tmux new -s devCreate named session
tmux attach -t devAttach to session
tmux lsList sessions
Ctrl+B, dDetach from session
Ctrl+B, $Rename session

Windows:

CommandDescription
Ctrl+B, cNew window
Ctrl+B, ,Rename window
Ctrl+B, nNext window
Ctrl+B, pPrevious window
Ctrl+B, 0-9Switch to window by number
Ctrl+B, &Close window

Scrollback:

CommandDescription
Ctrl+B, [Enter scroll mode
Arrow keys / PgUp/PgDnScroll
qExit scroll mode
/Search forward (in scroll mode)
?Search backward (in scroll mode)

Terminal Multiplexer: Zellij (Alternative)

Zellij is a modern terminal multiplexer with a more discoverable UI. If you find tmux's keybindings hard to remember, Zellij might suit you better.

When to Choose Zellij

  • You prefer on-screen hints for keybindings
  • You want a more modern, batteries-included experience
  • You don't need custom title format propagation

Limitation: Title Customization

Unlike tmux's set-titles-string, Zellij doesn't yet support customizing the terminal title format (issue #1495). Titles propagate automatically, but you can't configure the format like #S:#W.

If title customization matters for your Moshi workflow, stick with tmux.

Installation

brew install zellij

Small-Screen Configuration

Create ~/.config/zellij/config.kdl:

// Remove pane borders (saves screen space)
pane_frames false

// Simplified UI without decorative arrow fonts
simplified_ui true

// Use compact layout (minimal chrome)
default_layout "compact"

// Mouse support
mouse_mode true

// Large scrollback
scroll_buffer_size 50000

The compact layout removes the status bar, giving you maximum terminal space on a phone screen.

Tip: Start sessions with a name to make the status bar more meaningful:

zellij -s claude

This shows "Zellij (claude)" instead of a random name like "friendly-tiger".

Zellij Cheatsheet

Zellij uses modes. Press Ctrl+G to see all available actions.

Basics:

CommandDescription
zellijStart new session
zellij -s devStart named session
zellij attach devAttach to session
zellij lsList sessions

Navigation (default mode):

CommandDescription
Ctrl+TTab mode
Ctrl+SScroll mode
Ctrl+OSession mode
Ctrl+QQuit

Tab Mode (Ctrl+T):

KeyDescription
nNew tab
h/lPrevious/next tab
1-9Go to tab by number
rRename tab
xClose tab

Scroll Mode (Ctrl+S):

KeyDescription
j/kScroll down/up
d/uHalf page down/up
/Search
n/NNext/previous match
EscExit scroll mode

Session Mode (Ctrl+O):

KeyDescription
dDetach
wSession manager

Network Layer

Before you can connect from your iPhone, you need a way to reach your Mac from anywhere.

Tailscale (Recommended)

Tailscale creates a secure mesh VPN using WireGuard. Every device gets a stable IP that works from anywhere—home, office, coffee shop, cellular.

Why Tailscale:

  • Zero configuration port forwarding
  • Works behind NAT and firewalls
  • Peer-to-peer (fast, no relay latency in most cases)
  • Free for personal use (up to 100 devices)

Mac setup:

# Install Tailscale (CLI only)
brew install tailscale
# Or install from Mac App Store for the menu bar GUI

# Start and authenticate
sudo tailscale up --ssh

# Get your Tailscale IP
tailscale ip
# Example: 100.64.0.1

The --ssh flag enables Tailscale SSH—you can SSH using your Tailscale identity without managing keys.

iPhone setup:

  1. Install Tailscale from the App Store
  2. Sign in with the same account
  3. Your Mac's Tailscale IP now works from your phone

WireGuard (Self-Hosted or Router Built-in)

If you prefer self-hosting, WireGuard gives you the same protocol benefits with full control. Many routers (UniFi, pfSense, OpenWrt, ASUS with Merlin) have WireGuard built-in—check your router's VPN settings.

brew install wireguard-tools

You'll need to set up a WireGuard server (or use a VPS as a relay) and configure keys manually.

Surge / Proxies (Restricted Networks)

If you're in an environment with restrictive firewalls (corporate networks, some countries), you might need a proxy layer:

  • Surge (Mac/iOS)
  • Shadowsocks
  • Custom SOCKS5/HTTP proxies

These can tunnel your mosh/SSH traffic through allowed ports (443, 80) when UDP is blocked.


iPhone Setup with Moshi

Moshi is the native iOS terminal built on mosh—purpose-built for AI agent workflows.

Initial Setup

  1. Install Tailscale from the App Store and sign in
  2. Install Moshi from the App Store
  3. Add your server:
    • Host: Your Mac's Tailscale IP (e.g., 100.64.0.1)
    • Username: Your Mac username
    • Authentication: SSH key (stored in Secure Enclave, protected by Face ID)

Enable Push Notifications

This is Moshi's killer feature for AI agent workflows.

  1. Open Moshi → Settings → Notifications
  2. Enable notifications and copy your webhook token

Configure Your AI Agent

Add this to your project's CLAUDE.md or AGENTS.md:

## Notifications

When you complete a task or need input, notify me:

curl -s -X POST https://api.getmoshi.app/api/webhook \
  -H "Content-Type: application/json" \
  -d '{"token": "YOUR_TOKEN", "title": "Status", "message": "Brief summary"}'

Replace YOUR_TOKEN with your Moshi webhook token.

Now when Claude Code needs approval or finishes a task, you get a push notification on your iPhone and Apple Watch. Tap to open Moshi directly into your session.

Voice Input

Moshi runs OpenAI's Whisper model locally on your iPhone:

  • Zero latency: No network round-trip
  • Technical accuracy: Understands code, paths, and technical terms
  • Privacy: Voice never leaves your device
  • Works offline: Subway, airplane mode, spotty cellular

When Claude asks "Should I run the migration?", hold the mic button, say "yes", release. Done.

Powerline Fonts

Moshi has built-in support for Powerline fonts. If your tmux status bar or shell prompt uses Powerline symbols, they'll render correctly without additional font installation.


Security Considerations

SSH Key-Only Authentication

Disable password authentication on your Mac:

# Edit SSH config
sudo nano /etc/ssh/sshd_config

# Add or modify these lines:
PasswordAuthentication no
ChallengeResponseAuthentication no

# Restart SSH
sudo launchctl stop com.openssh.sshd
sudo launchctl start com.openssh.sshd

With Tailscale SSH (--ssh flag), this is handled automatically—authentication uses your Tailscale identity.

Why VPN over Port Forwarding

Never expose SSH (port 22) or mosh (UDP 60000-61000) directly to the internet.

ApproachRisk
Port forwardingExposed to entire internet, constant brute-force attempts
Tailscale/WireGuardOnly accessible to your authenticated devices

Tailscale and WireGuard create a private network. Your Mac isn't visible to the public internet at all.

Firewall

If using Tailscale, no firewall changes needed—traffic flows over the Tailscale interface.

If self-hosting WireGuard or exposing services directly:

# macOS firewall (allow mosh)
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add /usr/local/bin/mosh-server

The Complete Workflow

Here's how it all fits together:

┌─────────────────────────────────────────────────────────────────┐
│                        Your Mac                                 │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │                     tmux session                           │ │
│  │                                                            │ │
│  │  $ claude                                                  │ │
│  │  > Implementing authentication...                          │ │
│  │  > Need permission to run: npm install bcrypt              │ │
│  │  > [Waiting for approval]                                  │ │
│  │  > curl → Moshi webhook                                    │ │
│  └────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
                ┌───────────────────────────┐
                │     Push Notification     │
                │    → iPhone / Watch       │
                └─────────────┬─────────────┘
                              │
                ┌─────────────▼──────────────┐
                │       Your iPhone          │
                │                            │
                │  "Claude needs approval"   │
                │                            │
                │  [Tap] → Moshi opens       │
                │  mosh reconnects instantly │
                │  tmux session waiting      │
                │  Say "yes" → done          │
                └────────────────────────────┘

The daily flow:

  1. Start your agent on your Mac in a tmux session
  2. Detach and walk away—go to work, run errands, sleep
  3. Get notified when Claude needs input
  4. Tap notification—Moshi connects in seconds
  5. Approve by voice—agent continues
  6. Repeat—your agent works endlessly

Your working machine stays clean. Your agent runs 24/7. You're always reachable.


Complete Setup Checklist

Mac

# 1. Install tools
brew install mosh tmux tailscale

# 2. Configure tmux
cat >> ~/.tmux.conf << 'EOF'
set -g history-limit 50000
set -g mouse on
set -g set-titles on
set -g set-titles-string "#S:#W"
EOF

# 3. Start Tailscale
sudo tailscale up --ssh
tailscale ip  # Note this IP

# 4. Enable Remote Login
# System Settings → General → Sharing → Remote Login

# 5. Prevent sleep
# System Settings → Energy Saver → Prevent automatic sleeping

Project Configuration

Add to CLAUDE.md or AGENTS.md:

## Notifications

When you complete a task or need input, notify me:

curl -s -X POST https://api.getmoshi.app/api/webhook \
  -H "Content-Type: application/json" \
  -d '{"token": "YOUR_TOKEN", "title": "Status", "message": "Brief summary"}'

iPhone

  1. Install Tailscale → sign in
  2. Install Moshi
  3. Add server with Tailscale IP
  4. Settings → Notifications → copy webhook token
  5. Add token to project CLAUDE.md

FAQ

Why not use a VPS?

You can use a VPS. But your Mac gives you macOS-specific tooling (Xcode, Simulator, Apple frameworks), local network access for IoT/home automation work, and no monthly fees. For iOS developers, a Mac is often required anyway.

What if I lose internet on my phone?

Mosh handles this gracefully. Your session doesn't die—it waits. When connectivity returns, mosh reconnects automatically. Your tmux session and Claude agent keep running regardless.

How much does this cost?

  • Tailscale: Free for personal use
  • Moshi: Free (Premium available)

Does the agent keep running if I close Moshi?

Yes. The agent runs in tmux on your Mac. Moshi is just a window into that session. Close Moshi, and the agent continues. Open Moshi, and you're back where you left off.

What about iPad?

Same setup. Moshi works on iPad with the same features.

tmux or Zellij?

tmux if you want customizable title propagation and a battle-tested tool. Zellij if you prefer a modern UI with on-screen hints. Both work with Moshi.


Resources