It's 2am, you connect from your laptop at home to that rented cloud Mac mini, ready to pick up the build you left running earlier in the day. VS Code pops up an "Installing remote extensions" progress bar that spins for a full forty seconds — the extension list is identical to yesterday's, yet it's being reinstalled from scratch. That "meeting for the first time, every time" experience is usually the first trap people hit when they move their editor to a cloud Mac. Waiting further down the road: dropped sessions on flaky networks, and graphical debugging that simply doesn't work. This post walks through all three.
Why move your editor to a cloud Mac instead of developing locally
If you only log in occasionally to run xcodebuild once, plain SSH plus typing commands is fine. But if you're writing code, debugging, and running tests on a cloud Mac mini day in and day out, a bare terminal with vim is noticeably worse than a local IDE — no semantic jump-to-definition, no breakpoint debugging, and clipboard sync needs extra setup. The better approach is to let the Mac mini handle only compute and compilation, while keeping the editor UI local, bridged over a remote protocol. That's really the point of a "cloud Mac" service: the machine is a dedicated physical resource you treat as your own computer sitting in a data center — not a disposable container you spin up and throw away.
Bridging to a cloud Mac with VS Code Remote-SSH
VS Code Remote-SSH works on a simple principle: the local side runs only a thin client, while the actual language services, terminal, and filesystem all live on the remote Mac. On first connection it installs a vscode-server binary and an extension host into ~/.vscode-server on the remote machine; subsequent connections reuse that same environment.
SSH config and connection multiplexing
By default, every connection redoes a full TCP + SSH handshake, and when you're reaching across the Pacific to an APAC or US-West node, that latency shows up directly as "opening a file takes a beat." Using ControlMaster for connection multiplexing eliminates most of that handshake overhead:
# ~/.ssh/config
Host omac-jp
HostName <your node IP>
User devuser
Port 22
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h-%p
ControlPersist 10m
ServerAliveInterval 30
ServerAliveCountMax 3
ControlPersist 10m means that after the master connection's window closes, the shared channel stays alive for 10 more minutes — any new terminal tab or VS Code reconnect during that window rides the existing channel, skipping the crypto renegotiation entirely. ServerAliveInterval guards against ISPs whose NAT quietly kills idle connections.
Extension caching and index warm-up
That "reinstalling extensions every time" issue mentioned earlier usually isn't a VS Code bug — it's that the remote host itself changed between connections, e.g. you reimaged the instance from the console, or switched to a different one. As long as you stick to the same machine, everything in ~/.vscode-server — extensions, language server caches, TypeScript/Swift indexes — persists across sessions, and connections after the first should feel instant.
For larger projects (say, an Xcode project with multiple targets), you can pre-warm the cache by running a full index pass on the remote before disconnecting:
cd ~/Projects/MyApp
xcodebuild -project MyApp.xcodeproj -scheme MyApp -showBuildSettings > /dev/null
This doesn't produce an executable, but it does get Xcode's index database built ahead of time, so jump-to-definition in the editor won't need to rebuild it on the spot.
Where JetBrains Gateway fits — and where it doesn't
If your team also runs backend services (say, a Kotlin/Go API) on the same cloud Mac, JetBrains Gateway is another option: a lightweight local client connects to a full IDE backend running remotely (IntelliJ IDEA, GoLand, etc.), with rendering streamed back over a proprietary protocol — closer to a native feel than a plain web IDE.
Gateway's boundary is clear: it serves language ecosystems that have a corresponding JetBrains IDE. Apple-exclusive tooling — Xcode projects, Interface Builder, Swift Playgrounds — is outside its coverage.
In other words, for pure iOS/macOS development on a cloud Mac, your main toolchain is still VS Code Remote-SSH (for writing code, running scripts, tailing logs) paired with xcodebuild in a terminal. Gateway is a better fit for teams that happen to also run backend services on that same Mac.
Keeping sessions alive with tmux against flaky networks
Whichever remote editing setup you use, as long as the underlying connection is SSH, disconnection risk is baked in — switching Wi-Fi networks on the road, a home router rebooting, anything can sever the connection instantly. If that happens mid-way through a 40-minute build, the build process gets killed and all that progress is lost.
The fix is to launch every long-running task inside a tmux session rather than directly under the SSH session:
ssh omac-jp
tmux new -s build
xcodebuild -workspace MyApp.xcworkspace -scheme MyApp \
-destination 'generic/platform=iOS' build 2>&1 | tee build.log
After reconnecting, running tmux attach -t build picks right back up where the terminal output left off — the build process is completely unaffected. This habit isn't just for builds; long model fine-tuning runs, log tailing, and fastlane packaging scripts should all live inside tmux too.
| Scenario | Recommended tool | Why |
|---|---|---|
| Day-to-day coding, log watching | VS Code Remote-SSH | Semantic navigation + integrated terminal, fast once connections are multiplexed |
| Team backend services (non-Xcode) | JetBrains Gateway | Full IDE experience, but no Xcode project support |
| Long-running tasks (builds/training) | tmux / screen | Disconnects don't kill the process; reattach anytime |
| GUI needed (Instruments, Interface Builder) | Screen sharing / VNC | The only way to see the actual GUI |
Handling graphical debugging: the VNC/screen-sharing trade-off
The command line covers most scenarios, but some work can't avoid a GUI: reading a memory timeline in Instruments, tweaking constraints in Interface Builder, or just confirming what a UI actually looks like when rendered. For those, you switch to screen sharing (VNC), and the experience is a different animal — far more latency-sensitive. Dropping the resolution to what you actually need (say 1440×900 instead of 4K) and setting color depth to the "thousands of colors" tier noticeably improves smoothness over cross-region links. For daily work, stick to SSH plus your editor and only spin up the GUI on demand — don't leave VNC running and eating bandwidth in the background.
Checklist and lessons learned
Before you put this workflow into practice, run through the following:
- Set up
ControlMaster/ControlPersistin your SSH config to cut repeated handshake latency; - Stick to the same instance — don't reimage frequently, or your extension cache and indexes will keep rebuilding from scratch;
- Wrap anything that takes more than a few minutes inside
tmux— never run it directly under a bare SSH session; - Know Gateway's limits for Xcode work — don't expect it to take over Apple's graphical toolchain;
- Spin up VNC only when you actually need graphical debugging, and dial resolution/color depth down for smoothness;
- Which machine types and nodes are actually available depends on what's currently offered in the console — plan your bandwidth and latency expectations around that.
Frequently asked questions
Why do VS Code Remote-SSH extensions get reinstalled on every reconnect?
Extensions live under ~/.vscode-server on the remote host, so they persist as long as you keep connecting to the same instance and don't wipe that directory; reinstalls usually happen after switching to a different server or reimaging the OS, so pin one instance for the rental period.
Does JetBrains Gateway work for Xcode-based development?
Gateway targets languages with a matching JetBrains IDE (JVM, Node, Go, Python); it doesn't support Xcode projects, so Swift/Objective-C work still goes through VS Code Remote-SSH with xcodebuild in a terminal, or screen sharing when you need the Xcode GUI.
Will a flaky network kill a build running over SSH?
Not if the build was started inside a tmux or screen session — the process keeps running after the SSH link drops, and reattaching with tmux attach picks the output back up without a rerun.
HireVPS
Try a dedicated cloud Mac mini today
Rent by the day, get SSH/VNC credentials in 2 minutes, and upgrade your configuration anytime.