I saw this post about running Claude Code from a phone and immediately wanted the same thing. There were, however, two areas I thought we could improve upon: Vultr costs real money ($7/day when running), and Poke, a notification service, that is gated behind a truly ridiculous signup process.
So this is my spin on the Claude Code On-the-Go approach. Same idea, zero monthly cost, and notifications that just work.
Why Not Just Pay for a VPS?
You could. Vultr, Hostinger, AWS EC2, and countless other VPS providers work fine but come with costs and tradeoffs. You’re paying by the hour, so now you need lifecycle management. The setup outlined in the post includes vm-start and vm-stop scripts to spin the instance up and down. Forget to stop it, and you’re burning $7 a day. That mental overhead of remembering “Is my VM running? Did I shut it down?” defeats the purpose of a frictionless mobile workflow.
Oracle Cloud’s Always Free tier eliminates this entirely. You get Ampere A1 ARM instances with up to 4 OCPUs, 24 GB of RAM, and 200GB of storage for free. No trial period, no expiry. Leave it running 24/7, never think about it, never get a bill. That’s more horsepower than most paid VPS plans, and it costs nothing.
The catch: Oracle’s free tier capacity is notoriously hard to get. ARM instances on a plain free-tier account are almost always “out of capacity.” The fix is to upgrade to a Pay-as-you-Go account — you add a credit card, but as long as you stay within the Always Free limits, the charge is $0. PAYG accounts get priority access to the same free resources. I set a budget alert at $0.01 actual spend, so I’ll know immediately if anything crosses the free line.
I also put the whole thing in Terraform so I can tear it down and rebuild it without clicking through Oracle’s console. Two variables (compartment ID and region), terraform apply, done.
Why Ntfy Over Poke?
Poke is invitation-gated, and the onboarding is painful. Ntfy is the opposite. It’s a dead-simple pub/sub notification service, open source, free to use, and you can start sending push notifications in about 30 seconds:
curl -d "Hello from your VM" ntfy.sh/your-private-topic
Install the ntfy app on your phone, subscribe to your topic, and you’re done. No accounts, no API keys, no waiting for access. If you want more control later, you can self-host the server.
The Layers
Each layer solves one specific problem, and does not differ from the original approach:
Tailscale — The VM has no public SSH. Tailscale puts it on a private WireGuard mesh network. Install it on the VM and your phone, and they can talk to each other directly. No port forwarding, no security groups to misconfigure, no exposure.
Mosh — SSH over cellular is miserable. Switching between Wi-Fi and LTE is flaky. Get interrupted by a dead zone, and poof, your connection is gone. Mosh uses UDP, handles roaming natively, and reconnects automatically when your network comes back. It also does local echo prediction, so typing feels instant even on high-latency connections.
Tmux — Session persistence. If mosh reconnects (or you connect from a different device), tmux keeps your Claude Code session exactly where you left it. I have it set up to auto-attach on login, so when I connect, it drops me straight into my session:
# in .bashrc — auto-attach to tmux on SSH/mosh login
if [[ -z "$TMUX" ]] && [[ -n "$SSH_CONNECTION" || -n "$MOSH" ]]; then
tmux attach -t main 2>/dev/null || tmux new -s main
fi
Ntfy — The novel idea in this stack is marrying Claude Code’s hooks with a notification layer. Together, this makes the whole thing actually useful on mobile. Without notifications, you’d be constantly switching to your terminal to check if Claude is waiting for you. With ntfy, you get a push notification the moment Claude asks a question or finishes a task.
The Notification Hook
Claude Code has a hooks system that lets you run scripts in response to events. I use two hooks:
- PreToolUse — fires when Claude asks a question via
AskUserQuestion. The hook script extracts the question text and sends it as a notification. - Stop — fires when Claude finishes a task. Sends a “task complete” notification so I know to check the results.
The hook script is simple — it reads the event data from $CLAUDE_HOOK_EVENT_DATA, pulls out the relevant text, and curls ntfy:
# Simplified version of the hook
TOPIC="${NTFY_TOPIC}"
[ -z "$TOPIC" ] && exit 0 # no topic configured, skip silently
TOOL_NAME="$1"
case "$TOOL_NAME" in
question)
MESSAGE=$(echo "$CLAUDE_HOOK_EVENT_DATA" | jq -r '.tool_input.question // empty')
;;
*)
exit 0
;;
esac
curl -sS -d "$MESSAGE" "https://ntfy.sh/${TOPIC}" > /dev/null
The NTFY_TOPIC env var keeps the topic name out of dotfiles. On machines without ntfy configured, the script exits silently without errors or noise.
The Daily Workflow
Here’s what it actually looks like:
- Open Tailscale on my phone (ensures the VPN is active)
- Open Termius and tap my saved host — mosh connects and I land in tmux
- Start Claude Code on a task — “add pagination to the API endpoint” — then pocket my phone.
- Notification dings — ntfy notification: “Should I use cursor-based or offset-based pagination?”
- Open Termius, type “cursor-based”, pocket my phone again.
- Another Notification dings — “Task complete”
The latency between Claude asking a question and the push notification arriving is under 2 seconds. The whole interaction of pulling out the phone, responding, and putting it back down takes maybe 15 seconds.
For parallel work, I use tmux windows (Ctrl-a c for a new window, Ctrl-a n to cycle) and git worktrees so each Claude agent works in its own checkout.
Cost
| Component | Cost |
|---|---|
| Oracle Cloud ARM VM (4 OCPU, 24 GB) | Always Free |
| Tailscale | Free for personal use |
| Mosh | Open source |
| Tmux | Open source |
| Ntfy | Free hosted tier |
| Termius | Free tier works, premium is nice |
Total: $0/month. The Vultr equivalent would run $7/day.
Tips
- PAYG + budget alerts: Upgrade to Pay-as-you-Go for reliable ARM capacity, then set a $0.01 budget alert. You’ll get an email the instant any charge appears.
- Terraform: Don’t click through the Oracle console more than once. My Terraform stack provisions the instance, VCN, subnet, and gateway with two variables.
- UFW + fail2ban: Even behind Tailscale, I run UFW (allow only the
tailscale0interface) and fail2ban. Belt and suspenders. - Mosh ports: Allow UDP 60000-61000 on the Tailscale interface in UFW. Mosh needs these for its UDP connections.
- Battery: Mosh over Tailscale is easy on battery since it only sends data on changes.
- Phone keyboards: Termius has a configurable extra key row and it handles SSH keys and identities well.
Wrapping Up
Running Claude Code from your phone is a genuine workflow improvement, not a gimmick. Development fits into the gaps of your day: waiting for coffee, riding the train, sitting in the school pickup line. But there’s no reason to pay for it, and the notification layer should be something you can set up in 30 seconds, not something gated behind a waitlist.
Ready to try it out yourself? Just clone my repo and run terraform apply to set up your own always-free Claude Code environment. After that first commit gets pushed from your phone from some place far away from your keyboard, you’ll be hooked.