The Code tab in Claude Desktop can add an SSH connection and run Claude Code on a remote server. The app uploads the program to the server itself and takes care of authentication, so you don’t need to install Claude on the server or sign in there.
The catch: if the server’s outbound connection can’t reach Anthropic (a server in a region Anthropic doesn’t serve, such as Hong Kong, gets refused), or you want to pin it to a specific egress, the remote Claude can’t send its requests. The fix is to give Claude on the server its own proxy. It only affects Claude and leaves the rest of the machine’s networking alone.
Rather not do this by hand? I packaged the whole procedure as a skill. Once it’s installed, tell Claude “set up the Claude proxy on server xxx” and it checks, writes the config, restarts and verifies on its own. Installing it, or handing the job to an AI in one copied line, is covered in Automating it with a skill at the end.
Symptoms
You connect from the desktop app, send a message, and nothing comes back, or the session sits at “Starting session…”.
Try the API directly from the server:
curl -sI https://api.anthropic.com | head -1
A 403 almost always means the egress region is blocked. On a machine that can reach the API, an unauthenticated request usually gets 401 or 405.
1. Write Claude’s settings on the server
SSH into the server and, in the home directory of the user you’ll connect as, edit ~/.claude/settings.json:
{
"env": {
"HTTPS_PROXY": "http://127.0.0.1:7890",
"HTTP_PROXY": "http://127.0.0.1:7890",
"NO_PROXY": "localhost,127.0.0.1,192.168.0.0/16"
}
}
- Replace
127.0.0.1:7890with your own proxy. It can run on the server itself or be a gateway on your LAN, such ashttp://192.168.1.2:7890. - HTTP or HTTPS proxies only. The official docs state that Claude Code does not support SOCKS proxies. A Clash / mihomo mixed port speaks HTTP too, so
http://works. - If the proxy needs authentication, put the credentials in the URL:
https://user:pass@proxy.example.com:443. URL-encode special characters such as@or:in the password. The password sits in the file in plain text, sochmod 600 ~/.claude/settings.json. NO_PROXYlists destinations that should skip the proxy, such as localhost and your LAN. If you use Tailscale, add100.64.0.0/10,.ts.net.- If the file already exists, merge the
envblock into it instead of overwriting the file.
Check that the JSON is valid:
jq . ~/.claude/settings.json
This
envapplies only to Claude and the commands it runs in a session. A shell you open with plain SSH stays clean, and the rest of the machine’s networking is unaffected.
2. Add the SSH connection in the desktop app
In the Code tab’s environment dropdown, choose “+ Add SSH connection”, fill in the host, user, port and private key, then start a session and send a message.
There’s no need to run claude and sign in on the server. Your account stays signed in only on your own computer, which means one less login record and a cleaner picture for Anthropic’s risk checks.
3. If you’ve connected before: stop the old remote server
The remote server the desktop app starts on the machine is a long-lived process that later connections reuse. It reads its configuration when it first starts, so editing settings.json afterwards doesn’t take effect by itself.
After changing the settings, stop it on the server:
pkill -f 'claude/remote/srv/.*/server'
The next time the app connects, it starts a fresh one that picks up the proxy settings.
If you run this remotely as
ssh host "pkill -f ...",pkillcan match and kill the shell running the command. Running it from a login shell on the server avoids that.
Why not SetEnv in the SSH config
My first idea was to pass the proxy variables with SetEnv in my local ~/.ssh/config. That doesn’t work:
SetEnvis only accepted when the server’s sshd allows it withAcceptEnv. The default allows justLANGandLC_*; everything else is silently dropped.- Even with sshd changed, the desktop app doesn’t necessarily honor
SetEnvfrom your~/.ssh/config. - The remote server is reused, so its environment is fixed at its first start.
~/.claude/settings.json is the reliable place: Claude reads it no matter which host alias or SSH client the connection came from.
Verifying
The easiest check is to ask Claude to run this in the remote session:
env | grep -i proxy
If the three variables show up, it’s working.
You can also look at the Claude process’s connections on the server. They should all go to your proxy’s address and port:
ss -tnp | grep claude
Don’t judge by
/proc/<pid>/environ. Claude applies theenvfromsettings.jsonafter it starts, while/procrecords the environment at process launch, so the proxy variables not appearing there is expected.
Things to watch
- Think twice on small machines. The Claude program the app drops into
~/.claude/remote/is about 230 MB on disk. Memory as I measured it: the long-lived remote server (server --serveplus--bridge) takes about 20 MB in total, and each session starts its own Claude process at about 270 MB, peaking around 330 MB, not counting whatever commands Claude runs. On a 1 GB VPS, a single session is already tight.
Automating it with a skill
I turned the steps above into an Agent Skill. It:
- Finds the proxy URL: if Claude’s memory or notes already have one, it asks you to confirm it; it also looks for existing settings and running proxies on the server, and asks you when it finds nothing. If your own computer has a proxy, it can lend it to the server over an SSH reverse tunnel.
- Tests the API from the server, direct and through the proxy, and won’t write a proxy that doesn’t work.
- Merges the proxy into
~/.claude/settings.json, keeping what’s there, with a backup and mode 600. - Stops the old remote server, asking first if a session is still running.
- After you connect once from the desktop app, checks that Claude’s connections all go through the proxy.
Claude Code, run on your own computer:
/plugin marketplace add ma-wenqian/skills
/plugin install claude-ssh-proxy@vinkey-skills
Other agents that support Agent Skills (Codex, Gemini CLI, Cursor and others): copy the repository’s skills/claude-ssh-proxy folder into that tool’s skills directory.
Hand it to an AI in one line
Or skip the commands: copy this line and send it to an AI that can run commands (Claude Code, Codex and the like). It installs the skill itself and gets started:
Install the claude-ssh-proxy skill from https://github.com/ma-wenqian/skills, then use it to set up a proxy for Claude on my remote server