| title | type | date |
|---|---|---|
Bento Remote Workflow Presentation |
docs |
2026-02-04 |
Modern AI-assisted development presents unique challenges:
- Long-running processes: AI coding sessions can run for hours, tying up your local machine
- Parallelization: Working on multiple features simultaneously requires isolated environments
- Connectivity: Losing connection to a local process means losing work
- Resource constraints: AI tools consume significant CPU/memory
graph TB
subgraph "Your Machine"
A[Happy Coder App<br/>Web / Mac / Native] --> |SSH + Notifications|B
end
subgraph "Bento Remote Server"
B[tmux Session Manager]
B --> C[Worktree 1<br/>feature-auth]
B --> D[Worktree 2<br/>bugfix-cart]
B --> E[Worktree 3<br/>refactor-api]
C --> F[Claude Code<br/>Instance 1]
D --> G[Claude Code<br/>Instance 2]
E --> H[Claude Code<br/>Instance 3]
end
subgraph "Git Repository"
I[(Main Repo)]
C -.-> I
D -.-> I
E -.-> I
end
Your cloud development environment that runs 24/7:
- Persistent compute that doesn't tie up your laptop
- Scales up for resource-intensive tasks
- Access from anywhere
2. tmux for Session Management
Terminal multiplexer that keeps processes alive:
- Detach/reattach without losing state
- Multiple windows and panes per session
- Survives SSH disconnections
Isolated working directories from a single repository:
- Work on multiple branches simultaneously
- No context switching overhead
- Each worktree is a complete working copy
AI-assisted development with enhanced UX:
- Claude Code: CLI-based AI coding assistant
- Happy Coder: Wrapper providing:
- Web interface for remote access
- Native Mac app with system integration
- Push notifications when tasks complete
- Cross-device interaction
sequenceDiagram
participant You as Developer
participant Happy as Happy Coder
participant Bento as Bento Remote
participant tmux as tmux Session
participant Graft as Git Worktree
participant Claude as Claude Code
You->>Happy: Start new task
Happy->>Bento: SSH connection
Bento->>tmux: Create/attach session
tmux->>Graft: graft new feature-x
Graft-->>tmux: New worktree ready
tmux->>Claude: Start Claude Code
Claude->>Claude: Work on feature...
Note over You,Claude: Connection can drop here
Claude-->>tmux: Task complete
tmux-->>Happy: Notification trigger
Happy-->>You: Push notification
You->>Happy: Reconnect & review
Challenge: When Claude Code completes a task in tmux, you have no way to know without constantly checking.
Solution: Custom macOS notifier
# After task completion in tmux, trigger notification
notify-macos "Claude Code finished: feature-auth complete"The notifier sends push notifications through Happy Coder to your Mac.
Challenge: Each worktree consumes disk space. Large monorepos can exhaust storage quickly.
Solutions:
- Larger Bento instance: Scale up storage as needed
- Sparse checkout with Graft: Only checkout files you need
# Configure graft for sparse checkout by default
graft config set sparse-default true
# Create worktree with sparse checkout
graft new feature-x src/ tests/Challenge: Default tmux is bare-bones and awkward to use.
Solutions:
| Issue | Solution |
|---|---|
| No mouse support | Enable in .tmux.conf: set -g mouse on |
| Ugly default theme | Use Catppuccin theme for better visuals |
| Missing features | Add plugins via TPM (Tmux Plugin Manager) |
Recommended .tmux.conf additions:
# Mouse support
set -g mouse on
# Catppuccin theme
set -g @plugin 'catppuccin/tmux'
# Useful plugins
set -g @plugin 'tmux-plugins/tmux-sensible'
set -g @plugin 'tmux-plugins/tmux-resurrect'
set -g @plugin 'tmux-plugins/tmux-continuum'| Traditional Local Dev | Cloud Workflow with This Stack |
|---|---|
| Process dies if laptop sleeps | Runs 24/7 on Bento |
| One task at a time | Parallel worktrees |
| No notifications | Happy Coder push alerts |
| Resource constrained | Scale up as needed |
| Lose work on disconnect | tmux preserves everything |
# 1. Connect to Bento
ssh bento
# 2. Start or attach tmux
tmux new -s dev || tmux attach -t dev
# 3. Create worktree for new feature
graft new my-feature
# 4. Start Happy (Claude Code wrapper) in that worktree
cd worktrees/my-feature
happy
# 5. Detach and let it run (Ctrl+B, D)
# Happy Coder will notify you when donegraph LR
subgraph "Input Layer"
A[Happy Web]
B[Happy Mac]
C[Happy Mobile]
end
subgraph "Transport"
D[SSH Tunnel]
E[Notification Service]
end
subgraph "Compute Layer"
F[Bento Remote]
G[tmux]
end
subgraph "Isolation Layer"
H[Graft Worktrees]
end
subgraph "AI Layer"
I[Claude Code Instances]
end
A --> D
B --> D
C --> D
D --> F
F --> G
G --> H
H --> I
I --> E
E --> A
E --> B
E --> C
- Persistent compute: Never lose work to laptop sleep or network issues
- True parallelism: Multiple Happy/Claude instances on isolated worktrees
- Stay informed: Notifications bring updates to you
- Scale on demand: Bigger problems = bigger Bento instance
- Better UX: Happy Coder makes remote dev feel local
Things that could be better:
| Issue | Current State | Ideal State |
|---|---|---|
| Worktree management | tmux windows don't map 1-1 with worktrees. Manual switching, easy to lose track of which window is which worktree. | Unified UI showing all worktrees with their status, easy switching, auto-create tmux window per worktree |
| Viewing diffs | CLI git diff output is hard to review for large changes. No syntax highlighting or side-by-side view. |
Rich diff viewer with syntax highlighting, side-by-side comparison, easy navigation between changed files |
This script sends desktop notifications that work through tmux + SSH to your local machine (via Ghostty terminal's OSC 9 support):
#!/bin/bash
# Send desktop notification that works in tmux + SSH + Ghostty
MSG="${1:-Notification}"
if [[ -n "$TMUX" ]]; then
PANE_TTY=$(tmux display-message -p "#{pane_tty}")
SESSION=$(tmux display-message -p "#{session_name}")
WINDOW=$(tmux display-message -p "#{window_name}")
FULL_MSG="[$SESSION:$WINDOW] $MSG"
printf '\ePtmux;\e\e]9;%s\a\e\\' "$FULL_MSG" > "$PANE_TTY"
elif [[ -n "$SSH_TTY" && -w "$SSH_TTY" ]]; then
printf '\033]9;%s\007' "$MSG" > "$SSH_TTY"
else
printf '\033]9;%s\007' "$MSG"
fiSave as ~/.local/bin/notify and make executable with chmod +x ~/.local/bin/notify.
# Tmux settings
# Set XTerm key bindings
setw -g xterm-keys on
# Set colors
set-option -g default-terminal "tmux-256color"
set -as terminal-features ",xterm-256color:RGB"
set -ga terminal-overrides ",xterm-256color:Tc"
set -g status-style fg=#ffffff,bg=#333333
# Enable passthrough for OSC sequences (notifications)
set -g allow-passthrough on
# Bell/notification settings for Claude Code
set -g visual-bell off
set -g bell-action any
set -g monitor-bell on
# Set reload key to r
unbind r
bind r source-file ~/.tmux.conf
# Count sessions start at 1
set -g base-index 1
# Set the title bar
set -g set-titles on
set -g set-titles-string '#(whoami) :: #h :: #(curl ipecho.net/plain;echo)'
# Enable scrollback
set -g terminal-overrides 'xterm*:smcup@:rmcup@'
# Static window names
set-option -g allow-rename off
# Increase scrollback buffer
set-option -g history-limit 50000
# Enable mouse support
set -g mouse on
# Status bar color
set -g status-right '#{prefix_highlight}'
# vim pane nav
bind-key h select-pane -L
bind-key j select-pane -D
bind-key k select-pane -U
bind-key l select-pane -R
set-option -g status-position top
# Configure the catppuccin plugin
set -g @catppuccin_flavor "mocha"
set -g @catppuccin_window_status_style "rounded"
# Window text: show both window name (#W) and pane title (#T)
set -g @catppuccin_window_text " #W: #T"
set -g @catppuccin_window_current_text " #W: #T"
# Make current window stand out (slightly lighter background)
# Inactive: #313244 (surface_0), Current: #585b70 (surface_2)
set -g @catppuccin_window_current_text_color "#585b70"
set -g @catppuccin_window_current_number_color "#f5c2e7"
# Make the status line pretty and add some modules
set -g status-right-length 100
set -g status-left-length 100
set -g status-left ""
set -ag status-right "#{E:@catppuccin_status_application}"
set -ag status-right "#{E:@catppuccin_status_directory}"
set -ag status-right "#{E:@catppuccin_status_session}"
# List of plugins
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'
set -g @plugin 'tmux-plugins/tmux-resurrect'
set -g @plugin 'tmux-plugins/tmux-continuum'
set -g @resurrect-strategy-nvim 'session'
set -g @plugin 'tmux-plugins/tmux-prefix-highlight'
set -g @plugin 'catppuccin/tmux#v2.1.3'
# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)
run '~/.tmux/plugins/tpm/tpm'