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 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 |
+-----------------------------+
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:
- around $12/month on-demand (if always on)
- 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.
The Setup
Prerequisites
- 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"
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
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,
};
3. 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-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
Using It
Browser: https://dev.yourdomain.com → enter password → VS Code
SSH: 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.
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),
});
}
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 it
- Init script fetches it at boot via
aws ssm get-parameter --with-decryption - Password never touches user-data or logs
Cost Breakdown
| Config | $/month |
| EC2 t4g.small | ~$12 |
| EBS 30GB gp3 | ~$2.40 |
| Elastic IP | ~$3.60 |
| Route 53 | ~$0.50 |
| Total | ~$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
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"
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.
