Tools: Your AI Coding Agent Deserves Its Own Cloud Machine (2026)

Tools: Your AI Coding Agent Deserves Its Own Cloud Machine (2026)

Why a Remote Dev Machine?

The Architecture

Step 1: Create the VM

Step 2: Install Everything on the VM

Step 3: Clone Your Project and Start Services

Step 4: SSH Tunnel to Localhost

Step 5: Run Claude Code in tmux

Step 6: Code from Your Phone with Happy

My Daily Workflow

Quick Reference I've been running Claude Code locally for months. It works, but my laptop fan sounds like a jet engine, my battery drains in two hours, and if I close the lid mid-session — gone. Last week I moved my entire dev environment to a cloud VM. Claude Code runs there, my full stack runs there, and I SSH tunnel everything back to localhost. From my laptop it feels identical. From my phone, I can check on my AI coding agent while grabbing coffee. Here's the exact setup. Every command is copy-pasteable. I verified each step end-to-end. If you don't have a GCP account yet, you get $300 in free credits for 90 days — no charge until you explicitly upgrade. That's more than enough to run this setup for months. Already have an account? Check your remaining credits at Billing → Overview in the console. What this setup costs: about $0.13/hour for the VM. With the free tier, you can run it ~2,300 hours — roughly 3 months of 24/7 usage, or 6+ months during work hours only. If you're a startup, apply for the Google for Startups Cloud Program — up to $200k in credits. Three reasons pushed me off localhost: The tradeoff is latency. SSH tunneling adds a few milliseconds. I can't feel it. Your laptop and phone are thin clients. The VM does all the work. I'm using Google Cloud because my Claude Code runs on Vertex AI (covered that in my previous post). But this works with any cloud provider. First, make sure you have the gcloud CLI installed. If not: Then authenticate and set your project: That's 4 vCPUs, 16GB RAM, 50GB SSD. Costs about $0.13/hour — covered by your free credits. Then run these on the VM: Verify everything installed: Verify everything is running: You should see your containers up with status (healthy): Your full stack is running on the VM. Your laptop isn't doing anything yet. This is the key part. From your local machine (not the VM), forward the ports you need: Now open your browser: It's localhost. Your browser doesn't know the difference. Hot reload works. DevTools work. Save it as an alias (add to ~/.zshrc or ~/.bashrc on your local machine): SSH back into the VM and start Claude Code in a tmux session so it survives disconnects: If you're using Vertex AI (GCP credits for Claude), add these to ~/.bashrc on the VM first: Then source ~/.bashrc before running claude. Claude Code now has your full project right there — files, Docker services, databases, everything. No latency. This changed my workflow. Happy is an open-source mobile client for Claude Code. End-to-end encrypted. On the VM, in a new tmux session: The --dangerously-skip-permissions flag runs Claude Code in "yolo mode" — no permission prompts. Remove it if you want the default safety checks. Happy shows a QR code. Scan it with the Happy app: That's it. You control Claude Code from your phone. When you get back to your desk, press any key on your keyboard and control switches back. I use this constantly. Standing in line? Check if tests passed. On a call? Glance at what Claude is building. Open localhost:3100. Everything is already running from yesterday. No cold start. During the day:

Claude Code runs in tmux on the VM. Attach when I need it, detach when I don't. Laptop stays cool. Away from desk:Happy app on my phone. "Run the test suite." "Show me the API logs." End of day:

Close the laptop. VM keeps running. Tomorrow: dev-tunnel and I'm back in 2 seconds. All covered by the $300 free credits for about 3 months. Auto-stop to save money: Use autossh for reliable tunnels — SSH tunnels drop. autossh reconnects: VS Code Remote SSH — connect your IDE directly to the VM: Multiple projects on one VM: Your laptop should be a thin client. Let the cloud do the heavy lifting. Part 2 of my Claude Code on Google Cloud series. Part 1: Run Claude Code on Google Cloud Templates let you quickly answer FAQs or store snippets for re-use. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse

Command

Copy

$ ┌─────────────┐ SSH Tunnel ┌──────────────────────┐ │ Laptop │ ──────────────────> │ Cloud VM │ │ localhost │ port forwarding │ ├── Your App │ └─────────────┘ │ ├── API Server │ │ ├── PostgreSQL │ ┌─────────────┐ Happy (E2E) │ ├── Redis │ │ Phone │ ──────────────────> │ └── Claude Code │ │ Happy App │ encrypted sync │ (in tmux) │ └─────────────┘ └──────────────────────┘ ┌─────────────┐ SSH Tunnel ┌──────────────────────┐ │ Laptop │ ──────────────────> │ Cloud VM │ │ localhost │ port forwarding │ ├── Your App │ └─────────────┘ │ ├── API Server │ │ ├── PostgreSQL │ ┌─────────────┐ Happy (E2E) │ ├── Redis │ │ Phone │ ──────────────────> │ └── Claude Code │ │ Happy App │ encrypted sync │ (in tmux) │ └─────────────┘ └──────────────────────┘ ┌─────────────┐ SSH Tunnel ┌──────────────────────┐ │ Laptop │ ──────────────────> │ Cloud VM │ │ localhost │ port forwarding │ ├── Your App │ └─────────────┘ │ ├── API Server │ │ ├── PostgreSQL │ ┌─────────────┐ Happy (E2E) │ ├── Redis │ │ Phone │ ──────────────────> │ └── Claude Code │ │ Happy App │ encrypted sync │ (in tmux) │ └─────────────┘ └──────────────────────┘ # macOS -weight: 500;">brew -weight: 500;">install google-cloud-sdk # Or download from https://cloud.google.com/sdk/docs/-weight: 500;">install # macOS -weight: 500;">brew -weight: 500;">install google-cloud-sdk # Or download from https://cloud.google.com/sdk/docs/-weight: 500;">install # macOS -weight: 500;">brew -weight: 500;">install google-cloud-sdk # Or download from https://cloud.google.com/sdk/docs/-weight: 500;">install gcloud auth login gcloud config set project YOUR_PROJECT_ID gcloud auth login gcloud config set project YOUR_PROJECT_ID gcloud auth login gcloud config set project YOUR_PROJECT_ID gcloud compute instances create my-dev-vm \ --zone=us-central1-a \ --machine-type=e2-standard-4 \ --boot-disk-size=50GB \ --boot-disk-type=pd-ssd \ --image-family=ubuntu-2404-lts-amd64 \ --image-project=ubuntu-os-cloud gcloud compute instances create my-dev-vm \ --zone=us-central1-a \ --machine-type=e2-standard-4 \ --boot-disk-size=50GB \ --boot-disk-type=pd-ssd \ --image-family=ubuntu-2404-lts-amd64 \ --image-project=ubuntu-os-cloud gcloud compute instances create my-dev-vm \ --zone=us-central1-a \ --machine-type=e2-standard-4 \ --boot-disk-size=50GB \ --boot-disk-type=pd-ssd \ --image-family=ubuntu-2404-lts-amd64 \ --image-project=ubuntu-os-cloud gcloud compute ssh my-dev-vm --zone=us-central1-a gcloud compute ssh my-dev-vm --zone=us-central1-a gcloud compute ssh my-dev-vm --zone=us-central1-a # Docker -weight: 500;">curl -fsSL https://get.-weight: 500;">docker.com | sh -weight: 600;">sudo usermod -aG -weight: 500;">docker $USER newgrp -weight: 500;">docker # Node.js 22 + pnpm -weight: 500;">curl -fsSL https://deb.nodesource.com/setup_22.x | -weight: 600;">sudo bash - -weight: 600;">sudo -weight: 500;">apt-get -weight: 500;">install -y nodejs -weight: 600;">sudo -weight: 500;">npm -weight: 500;">install -g pnpm@9 # Claude Code -weight: 600;">sudo -weight: 500;">npm -weight: 500;">install -g @anthropic-ai/claude-code # Happy (mobile access to Claude Code) -weight: 600;">sudo -weight: 500;">npm -weight: 500;">install -g happy # tmux (persistent sessions) -weight: 600;">sudo -weight: 500;">apt-get -weight: 500;">install -y tmux # Docker -weight: 500;">curl -fsSL https://get.-weight: 500;">docker.com | sh -weight: 600;">sudo usermod -aG -weight: 500;">docker $USER newgrp -weight: 500;">docker # Node.js 22 + pnpm -weight: 500;">curl -fsSL https://deb.nodesource.com/setup_22.x | -weight: 600;">sudo bash - -weight: 600;">sudo -weight: 500;">apt-get -weight: 500;">install -y nodejs -weight: 600;">sudo -weight: 500;">npm -weight: 500;">install -g pnpm@9 # Claude Code -weight: 600;">sudo -weight: 500;">npm -weight: 500;">install -g @anthropic-ai/claude-code # Happy (mobile access to Claude Code) -weight: 600;">sudo -weight: 500;">npm -weight: 500;">install -g happy # tmux (persistent sessions) -weight: 600;">sudo -weight: 500;">apt-get -weight: 500;">install -y tmux # Docker -weight: 500;">curl -fsSL https://get.-weight: 500;">docker.com | sh -weight: 600;">sudo usermod -aG -weight: 500;">docker $USER newgrp -weight: 500;">docker # Node.js 22 + pnpm -weight: 500;">curl -fsSL https://deb.nodesource.com/setup_22.x | -weight: 600;">sudo bash - -weight: 600;">sudo -weight: 500;">apt-get -weight: 500;">install -y nodejs -weight: 600;">sudo -weight: 500;">npm -weight: 500;">install -g pnpm@9 # Claude Code -weight: 600;">sudo -weight: 500;">npm -weight: 500;">install -g @anthropic-ai/claude-code # Happy (mobile access to Claude Code) -weight: 600;">sudo -weight: 500;">npm -weight: 500;">install -g happy # tmux (persistent sessions) -weight: 600;">sudo -weight: 500;">apt-get -weight: 500;">install -y tmux -weight: 500;">docker --version # Docker 29+ node --version # v22+ claude --version # Claude Code 2.x tmux -V # tmux 3.x -weight: 500;">docker --version # Docker 29+ node --version # v22+ claude --version # Claude Code 2.x tmux -V # tmux 3.x -weight: 500;">docker --version # Docker 29+ node --version # v22+ claude --version # Claude Code 2.x tmux -V # tmux 3.x -weight: 500;">git clone https://github.com/your-org/your-project.-weight: 500;">git cd your-project -weight: 500;">docker compose up -d -weight: 500;">git clone https://github.com/your-org/your-project.-weight: 500;">git cd your-project -weight: 500;">docker compose up -d -weight: 500;">git clone https://github.com/your-org/your-project.-weight: 500;">git cd your-project -weight: 500;">docker compose up -d -weight: 500;">docker compose ps -weight: 500;">docker compose ps -weight: 500;">docker compose ps NAME STATUS PORTS my-app-api Up 3 min (healthy) 0.0.0.0:3000->3000/tcp my-app-web Up 3 min (healthy) 0.0.0.0:3100->3100/tcp my-app-postgres Up 5 min (healthy) 0.0.0.0:5432->5432/tcp my-app-redis Up 5 min (healthy) 0.0.0.0:6379->6379/tcp NAME STATUS PORTS my-app-api Up 3 min (healthy) 0.0.0.0:3000->3000/tcp my-app-web Up 3 min (healthy) 0.0.0.0:3100->3100/tcp my-app-postgres Up 5 min (healthy) 0.0.0.0:5432->5432/tcp my-app-redis Up 5 min (healthy) 0.0.0.0:6379->6379/tcp NAME STATUS PORTS my-app-api Up 3 min (healthy) 0.0.0.0:3000->3000/tcp my-app-web Up 3 min (healthy) 0.0.0.0:3100->3100/tcp my-app-postgres Up 5 min (healthy) 0.0.0.0:5432->5432/tcp my-app-redis Up 5 min (healthy) 0.0.0.0:6379->6379/tcp gcloud compute ssh my-dev-vm --zone=us-central1-a -- \ -L 3100:localhost:3100 \ -L 3000:localhost:3000 \ -N gcloud compute ssh my-dev-vm --zone=us-central1-a -- \ -L 3100:localhost:3100 \ -L 3000:localhost:3000 \ -N gcloud compute ssh my-dev-vm --zone=us-central1-a -- \ -L 3100:localhost:3100 \ -L 3000:localhost:3000 \ -N alias dev-tunnel='gcloud compute ssh my-dev-vm --zone=us-central1-a -- \ -L 3100:localhost:3100 -L 3000:localhost:3000 -N' alias dev-tunnel='gcloud compute ssh my-dev-vm --zone=us-central1-a -- \ -L 3100:localhost:3100 -L 3000:localhost:3000 -N' alias dev-tunnel='gcloud compute ssh my-dev-vm --zone=us-central1-a -- \ -L 3100:localhost:3100 -L 3000:localhost:3000 -N' gcloud compute ssh my-dev-vm --zone=us-central1-a gcloud compute ssh my-dev-vm --zone=us-central1-a gcloud compute ssh my-dev-vm --zone=us-central1-a tmux new -s claude cd ~/your-project claude tmux new -s claude cd ~/your-project claude tmux new -s claude cd ~/your-project claude export CLAUDE_CODE_USE_VERTEX=1 export ANTHROPIC_VERTEX_PROJECT_ID=YOUR_PROJECT_ID export CLOUD_ML_REGION=global export ANTHROPIC_MODEL=claude-opus-4-6 export CLAUDE_CODE_USE_VERTEX=1 export ANTHROPIC_VERTEX_PROJECT_ID=YOUR_PROJECT_ID export CLOUD_ML_REGION=global export ANTHROPIC_MODEL=claude-opus-4-6 export CLAUDE_CODE_USE_VERTEX=1 export ANTHROPIC_VERTEX_PROJECT_ID=YOUR_PROJECT_ID export CLOUD_ML_REGION=global export ANTHROPIC_MODEL=claude-opus-4-6 tmux new -s happy happy claude -- --dangerously-skip-permissions tmux new -s happy happy claude -- --dangerously-skip-permissions tmux new -s happy happy claude -- --dangerously-skip-permissions dev-tunnel # alias from Step 4 dev-tunnel # alias from Step 4 dev-tunnel # alias from Step 4 gcloud compute resource-policies create vm-maintenance workday-schedule \ ---weight: 500;">start-schedule="0 8 * * 1-5" \ ---weight: 500;">stop-schedule="0 20 * * 1-5" \ --timezone=UTC gcloud compute resource-policies create vm-maintenance workday-schedule \ ---weight: 500;">start-schedule="0 8 * * 1-5" \ ---weight: 500;">stop-schedule="0 20 * * 1-5" \ --timezone=UTC gcloud compute resource-policies create vm-maintenance workday-schedule \ ---weight: 500;">start-schedule="0 8 * * 1-5" \ ---weight: 500;">stop-schedule="0 20 * * 1-5" \ --timezone=UTC # Install: -weight: 500;">brew -weight: 500;">install autossh (macOS) or -weight: 500;">apt -weight: 500;">install autossh (Linux) autossh -M 0 -f -N \ -o "ServerAliveInterval 30" \ -o "ServerAliveCountMax 3" \ -L 3100:localhost:3100 \ -L 3000:localhost:3000 \ my-dev-vm # Install: -weight: 500;">brew -weight: 500;">install autossh (macOS) or -weight: 500;">apt -weight: 500;">install autossh (Linux) autossh -M 0 -f -N \ -o "ServerAliveInterval 30" \ -o "ServerAliveCountMax 3" \ -L 3100:localhost:3100 \ -L 3000:localhost:3000 \ my-dev-vm # Install: -weight: 500;">brew -weight: 500;">install autossh (macOS) or -weight: 500;">apt -weight: 500;">install autossh (Linux) autossh -M 0 -f -N \ -o "ServerAliveInterval 30" \ -o "ServerAliveCountMax 3" \ -L 3100:localhost:3100 \ -L 3000:localhost:3000 \ my-dev-vm Cmd+Shift+P → "Remote-SSH: Connect to Host" → my-dev-vm Cmd+Shift+P → "Remote-SSH: Connect to Host" → my-dev-vm Cmd+Shift+P → "Remote-SSH: Connect to Host" → my-dev-vm cd ~/project-a && -weight: 500;">docker compose -p project-a up -d # ports 3000-3100 cd ~/project-b && -weight: 500;">docker compose -p project-b up -d # ports 4000-4100 cd ~/project-a && -weight: 500;">docker compose -p project-a up -d # ports 3000-3100 cd ~/project-b && -weight: 500;">docker compose -p project-b up -d # ports 4000-4100 cd ~/project-a && -weight: 500;">docker compose -p project-a up -d # ports 3000-3100 cd ~/project-b && -weight: 500;">docker compose -p project-b up -d # ports 4000-4100 - Go to cloud.google.com/free - Click Get started for free - Sign in with your Google account, add a payment method (you won't be charged) - You now have $300 in credits - Battery and thermals — AI coding agents hammer your CPU. A cloud VM doesn't care. - Session persistence — Close your laptop, hop on your phone, come back to your desk. The session is still running. - Dev environment consistency — Docker, databases, everything runs 24/7 on the VM. No more "let me spin up Postgres first." - -L 3100:localhost:3100 — requests to localhost:3100 on your laptop go to port 3100 on the VM - -N — don't open a shell, just forward ports - http://localhost:3100 — your web app - http://localhost:3000 — your API - Ctrl+b d — detach (session keeps running in the background) - tmux attach -t claude — reattach from any SSH session - Close your laptop, come back tomorrow — session is exactly where you left it - iOS App Store - Google Play Store