I wanted the real Claude Code from anywhere: phone, random PC. Not the web version with its limitations—the actual CLI with plan mode, autonomous agents, and persistent workspace. So I built a quick thing. One command, max ~$18/month, full VS Code + Claude Code accessible from anywhere. The Problem Claude Code on claude.ai is nice for quick stuff, but it's not the same beast as the CLI: No plan modeNo long-running agents that can iterate autonomously Ephemeral filesystemEtc. No plan mode No long-running agents that can iterate autonomously Ephemeral filesystem Etc. The good stuff lives in the terminal. I wanted that on my phone. The Solution +-------------+ HTTPS/443 +-----------------------------+ | Browser | ---------------> | EC2 Instance | +-------------+ | +-- nginx (reverse proxy) | | +-- code-server (VS Code) | +-------------+ SSH/22 | +-- Claude Code CLI | | SSH Client | ---------------> | | +-------------+ +-----------------------------+ | v +-----------------------------+ | Route 53 (optional) | | dev.yourdomain.com -> IP | +-----------------------------+ +-------------+ HTTPS/443 +-----------------------------+ | Browser | ---------------> | EC2 Instance | +-------------+ | +-- nginx (reverse proxy) | | +-- code-server (VS Code) | +-------------+ SSH/22 | +-- Claude Code CLI | | SSH Client | ---------------> | | +-------------+ +-----------------------------+ | v +-----------------------------+ | Route 53 (optional) | | dev.yourdomain.com -> IP | +-----------------------------+ One EC2 instance. ARM64 because it's cheaper. code-server for VS Code in the browser. Claude Code CLI pre-installed. Done. Why the T4g instance? The t4g.small runs on AWS Graviton2: t4g.small around $12/month on-demand (if always on)2 vCPU, 2 GB RAMPerfect for this use case (Claude Code is mostly API calls, not local compute) around $12/month on-demand (if always on) around $12/month 2 vCPU, 2 GB RAM 2 vCPU, 2 GB RAM Perfect for this use case (Claude Code is mostly API calls, not local compute) Could go even cheaper with t4g.micro at ~$6/month if you're feeling adventurous with the RAM, or upgrade to t4g.small to get double the RAM. ~$6/month The Setup Prerequisites AWS CLI configuredNode.js 18+CDK (`npm install -g aws-cdk`)An EC2 key pairA domain you control5 minutes AWS CLI configured Node.js 18+ CDK (`npm install -g aws-cdk`) An EC2 key pair A domain you control 5 minutes 1. Store your password in SSM aws ssm put-parameter \ --name "/claude-server/code-server-password" \ --type SecureString \ --value "your-actual-strong-password" aws ssm put-parameter \ --name "/claude-server/code-server-password" \ --type SecureString \ --value "your-actual-strong-password" This is a one-time thing. Password stored securely, not floating around in CloudFormation templates or EC2 user-data logs. 2. Clone and configure git clone https://github.com/ThomasHoussin/claude-server cd claude-server npm install cp config/config.example.ts config/config.ts git clone https://github.com/ThomasHoussin/claude-server cd claude-server npm install cp config/config.example.ts config/config.ts Edit config/config.ts: export const config: Config = { region: 'us-east-1', domain: 'dev.yourdomain.com', hostedZoneId: 'ZXXXXXXXXXXXXX', // optional, for auto DNS useElasticIp: true, email: 'you@email.com', keyPairName: 'your-keypair', instanceType: 't4g.small', volumeSize: 30, }; export const config: Config = { region: 'us-east-1', domain: 'dev.yourdomain.com', hostedZoneId: 'ZXXXXXXXXXXXXX', // optional, for auto DNS useElasticIp: true, email: 'you@email.com', keyPairName: 'your-keypair', instanceType: 't4g.small', volumeSize: 30, }; 3. Deploy cdk bootstrap # first time only cdk deploy cdk bootstrap # first time only cdk deploy That's it. 4. Wait a few minutes The init script does the boring stuff: Installs nginx, node, code-serverGrabs your password from SSMSets up HTTPS with Let's Encrypt (automatic)Installs Claude Code CLI Installs nginx, node, code-server Grabs your password from SSM Sets up HTTPS with Let's Encrypt (automatic) Installs Claude Code CLI If you want to have a look or to debug: ssh ec2-user@dev.yourdomain.com tail -f /var/log/user-data.log ssh ec2-user@dev.yourdomain.com tail -f /var/log/user-data.log Using It Browser: https://dev.yourdomain.com → enter password → VS Code https://dev.yourdomain.com SSH: ssh ec2-user@dev.yourdomain.com → claude ssh ec2-user@dev.yourdomain.com claude If you enabled SSH password auth in the config, the instance reuses your SSM password. No keys to manage on mobile, just password and go. I use WebSSH on iOS for SSH, tabby for terminal, but any other should work. When using claude for the first time you'll need to authenticate (works on ssh with challenge/response). GitHub CLI is also installed ; use gh auth login to login; I created a classic token on https://github.com/settings/tokens with repo, workflow and read:org. Paste in terminal when asked and you're good to go. gh auth login https://github.com/settings/tokens After that my workflow is: start Claude in Plan mode; have it plan the requested changes, but make it work on a new branch, commit and create a PR at the end. This allows to review the modifications in the browser (and it triggers the review if configured on the repo). What's Actually Happening DNS management I use an Elastic IP so CDK can create the Route 53 record at deploy time: if (config.useElasticIp && config.hostedZoneId) { new ARecord(this, 'DevServerDNS', { zone: hostedZone, recordName: config.domain, target: RecordTarget.fromIpAddresses(eip.attrPublicIp), }); } if (config.useElasticIp && config.hostedZoneId) { new ARecord(this, 'DevServerDNS', { zone: hostedZone, recordName: config.domain, target: RecordTarget.fromIpAddresses(eip.attrPublicIp), }); } You could do it on the instance with a script, but then you need to give EC2 Route 53 permissions. I don't love that. Password flow You create a SecureString in SSM (once)CDK gives the EC2 role permission to read itInit script fetches it at boot via aws ssm get-parameter --with-decryptionPassword never touches user-data or logs You create a SecureString in SSM (once) CDK gives the EC2 role permission to read it Init script fetches it at boot via aws ssm get-parameter --with-decryption aws ssm get-parameter --with-decryption Password never touches user-data or logs Cost Breakdown Config$/monthEC2 t4g.small~$12EBS 30GB gp3~$2.40Elastic IP~$3.60Route 53~$0.50Total~$18.50 Config$/monthEC2 t4g.small~$12EBS 30GB gp3~$2.40Elastic IP~$3.60Route 53~$0.50Total~$18.50 Config$/monthEC2 t4g.small~$12EBS 30GB gp3~$2.40Elastic IP~$3.60Route 53~$0.50Total~$18.50 Config$/month Config Config $/month $/month EC2 t4g.small~$12 EC2 t4g.small ~$12 EBS 30GB gp3~$2.40 EBS 30GB gp3 ~$2.40 Elastic IP~$3.60 Elastic IP ~$3.60 Route 53~$0.50 Route 53 ~$0.50 Total~$18.50 Total Total ~$18.50 ~$18.50 Stop the instance when you're not using it, and it's basically just storage and IP costs. Why not Codespaces/Gitpod/other solution? There are probably many other solutions that could do the same thing. I liked the idea of having a simple solution that I can deploy and delete easily, and where I am completely in control. So, here we are. Cleanup cdk destroy cdk destroy Everything gone. Don't forget to delete your SSM parameter if you're truly done: aws ssm delete-parameter --name "/claude-server/code-server-password" aws ssm delete-parameter --name "/claude-server/code-server-password" That's It Claude Code in your pocket. Plan mode, agents, persistent workspace, the works. Code's on GitHub. It's like 200 lines of CDK and a bash script. Nothing fancy, but it works. GitHub