Get Moshi
Back to Articles

My Daily Moshi Workflow: How I Organize tmux for Claude Code

A practical guide to organizing tmux windows for AI agents, web servers, and Expo — with push notifications to stay in the loop

My Daily Moshi Workflow: How I Organize tmux for Claude Code

My Daily Moshi Workflow: How I Organize tmux for Claude Code

A practical guide to organizing tmux windows for AI agents, web servers, and Expo — with push notifications to stay in the loop


TL;DR: I run five tmux windows: 1-3 for Claude Code agents, 4 for web servers or Expo, 5 for misc tasks. Same layout across all projects — muscle memory means I can navigate without thinking. Claude Code sets window titles automatically, Moshi propagates them. Push notifications ping me when agents need input.


The Problem

Running AI coding agents alongside web or mobile development means juggling multiple processes. On desktop, you'd use multiple terminal tabs. On mobile, context-switching kills productivity.

My solution: a consistent tmux layout I can navigate blind.

┌─────────────────────────────────────────────────────────────────┐
│ dev ─ 1:frontend  2:api-refactor  3:tests  4:servers  5:bash    │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  Window 1: Claude working on frontend                           │
│  Window 2: Claude refactoring API                               │
│  Window 3: Claude running tests                                 │
│                                                                 │
│  Window 4: Web servers or Expo                                  │
│  Window 5: Misc (deploy, app store submit, etc.)                │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Note: Windows 1-3 don't need manual names. Claude Code automatically sets the terminal title based on current task, and Moshi propagates it to the tmux window name.


My tmux Configuration

Here's my ~/.tmux.conf:

# Large scrollback for long agent sessions
set -g history-limit 100000

# Mouse support (essential for mobile scrolling)
set -g mouse on

# Start numbering at 1 (matches keyboard shortcuts)
set -g base-index 1

# Show window index and title in terminal title
set -g set-titles on
set -g set-titles-string "#I: #W"

# Renumber windows when one closes
set -g renumber-windows on

Window Layout

I always use the same window numbers. Muscle memory matters.

WindowPurpose
1Primary Claude Code session
2Secondary agent (reviews, parallel tasks)
3Tertiary agent (tests, research)
4Web servers or Expo (if app)
5Misc (deploy, app store submit, etc.)

Windows 1-3 don't need manual names — Claude Code sets the terminal title automatically based on the current task (e.g., "frontend", "api-refactor", "tests"), and Moshi propagates it to the tmux status bar.

Creating the Layout

I have a script that sets this up:

#!/bin/bash
# ~/bin/dev-session

SESSION="dev"

tmux new-session -d -s $SESSION
tmux new-window -t $SESSION:2
tmux new-window -t $SESSION:3
tmux new-window -t $SESSION:4 -n servers
tmux new-window -t $SESSION:5 -n misc

# Start in window 1
tmux select-window -t $SESSION:1
tmux attach -t $SESSION

Or create manually:

tmux new -s dev
# Ctrl+B, c to create new windows

Navigating from Moshi

In Moshi, I use the tmux shortcuts panel constantly.

Long-press CtrlTmux tabTap window number

TapJumps to
1Claude (primary)
2Claude (secondary)
3Claude (tests)
4Servers / Expo
5Misc

The status bar shows where I am. Claude Code sets the terminal title automatically, and Moshi displays it in the header.

For a deeper dive into Moshi's shortcuts and modifier keys, see Mastering Moshi's Terminal Keyboard.


Push Notifications

This is the key to "endless agent" workflows. Each Claude session has this in the project's CLAUDE.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": "Task complete", "message": "Need approval for npm install"}'

Workflow

  1. Start Claude in windows 1-3 with different tasks
  2. Put phone in pocket
  3. Get notification: "Tests passing, ready for review"
  4. Open Moshi → check window titles in status bar → jump to the right one
  5. Approve and walk away

For the full push notification setup including webhook tokens and mosh/tmux configuration, see The Best Remote Coding Setup for AI Agents.


Window 4: Web Servers or Expo

Window 4 is for dev servers. For web projects, use Bun's parallel mode:

cd ~/projects/my-app && bun dev --filter '*'

This starts all workspace packages with dev scripts in parallel. For a monorepo:

// package.json
{
  "workspaces": ["apps/*", "packages/*"],
  "scripts": {
    "dev": "bun --filter '*' dev"
  }
}

Example output:

$ bun dev --filter '*'
[web] Server running at http://100.64.0.1:3000
[api] Server running at http://100.64.0.1:4000
[admin] Server running at http://100.64.0.1:3001

All servers in one window, one command. No panes needed.

For mobile apps, run Expo instead:

cd ~/projects/my-app && npx expo start

The Expo CLI has its own keyboard shortcuts (r to reload, i to open iOS Simulator) that work through Moshi.


Window 5: Misc

Window 5 is my scratch space for one-off tasks:

  • eas submit — submit to App Store
  • bun run deploy — deploy to production
  • gh pr create — create pull requests
  • Quick git operations
  • Anything that doesn't fit windows 1-4

I keep it named misc or bash so it's always there when I need it.


Previewing on Your Phone

When running dev servers, you want to tap a link and preview directly on your phone. Two things need to happen:

1. Bind to Network Interface

By default, Vite/Expo/Next.js bind to localhost — unreachable from your phone. Add --host:

FrameworkCommand
Vitevite --host or vite --host 0.0.0.0
Next.jsnext dev -H 0.0.0.0
ExpoAlready binds to network by default
Create React AppHOST=0.0.0.0 react-scripts start
Bunbun run --host 0.0.0.0 dev

Or configure permanently in vite.config.ts:

export default defineConfig({
  server: {
    host: true, // or '0.0.0.0'
  },
})

2. Tell Claude to Show the Address

Add this to your project's CLAUDE.md:

## Dev Server

When starting dev servers, always use --host flag to bind to network interface.

After the server starts, show me the network URL (not localhost) so I can tap to preview:

Example output:
> Server running at http://192.168.1.100:5173

Now when Claude starts your server, you'll see a tappable link in the terminal output. Tap it → opens in Safari → instant preview.

Using Tailscale IP

If you're connected via Tailscale (see Using Your Mac as a Remote Agent for setup), use your Mac's Tailscale IP:

# Get your Tailscale IP
tailscale ip -4
# Example: 100.64.0.1

# Server will be at http://100.64.0.1:5173

Add this to CLAUDE.md too:

My Tailscale IP is 100.64.0.1. When showing server URLs, use this IP instead of 192.168.x.x for reliable access.

Quick Preview Workflow

  1. Claude starts server with --host
  2. Terminal shows: http://100.64.0.1:5173
  3. Tap the link
  4. Safari opens with your app
  5. Make changes → Claude rebuilds → pull to refresh

Tips

Name Your Sessions Too

Not just windows — sessions. I use different sessions for different projects:

tmux new -s moshi        # Moshi development
tmux new -s client-app   # Client project
tmux new -s experiments  # Throwaway experiments

Moshi shows available sessions when you connect, so naming helps.

Quick Status Check

From any window, Ctrl+B, w shows a list of all windows. But tapping through 1-5 is usually faster.

Aggressive Scrollback

AI agents produce a lot of output. My history-limit 100000 means I can scroll back through an entire debugging session. Default 2000 lines isn't enough.


Quick Setup

# 1. Add to ~/.tmux.conf
cat >> ~/.tmux.conf << 'EOF'
set -g history-limit 100000
set -g mouse on
set -g base-index 1
set -g set-titles on
set -g set-titles-string "#I: #W"
set -g renumber-windows on
EOF

# 2. Create session script
cat > ~/bin/dev-session << 'EOF'
#!/bin/bash
SESSION="dev"
tmux new-session -d -s $SESSION
tmux new-window -t $SESSION:2
tmux new-window -t $SESSION:3
tmux new-window -t $SESSION:4 -n servers
tmux new-window -t $SESSION:5 -n misc
tmux select-window -t $SESSION:1
tmux attach -t $SESSION
EOF
chmod +x ~/bin/dev-session

# 3. Start working
dev-session

Resources