2.6 KiB
claude-ssh-setup
How Claude Code on this Windows machine reaches the sae-engineering server
(10.0.2.1, user sauer) over SSH.
TL;DR
OpenSSH on Windows can't load the .ppk key (NTFS permissions block it from
Git Bash, and the OpenSSH copy of the key fails the same way). PuTTY's plink
reads the PuTTY keystore natively and the host key is already trusted in the
Windows registry. cmd.exe mangles user@host (treats it as an AT job), so
invoke plink through powershell.exe instead.
Connection details
| Field | Value |
|---|---|
| Host | 10.0.2.1 |
| User | sauer |
| Key | C:\Users\richa\.ssh\id_ed25519.ppk (PuTTY) |
| Plink | C:\Program Files\PuTTY\plink.exe |
| pscp | C:\Program Files\PuTTY\pscp.exe |
Single command
powershell.exe -Command "& 'C:\Program Files\PuTTY\plink.exe' -i 'C:\Users\richa\.ssh\id_ed25519.ppk' -batch -l sauer 10.0.2.1 '<command>'"
-batch disables interactive prompts so the call fails fast in automation
instead of hanging.
Multiple commands
Chain with ; and avoid single quotes inside the remote command (the outer
single quotes are already in use):
powershell.exe -Command "& 'C:\Program Files\PuTTY\plink.exe' -i 'C:\Users\richa\.ssh\id_ed25519.ppk' -batch -l sauer 10.0.2.1 '/bin/cmd1; /bin/cmd2'"
For anything more complex, write a script locally and run it with the file-transfer recipe below.
File transfer (pscp)
"/c/Program Files/PuTTY/pscp.exe" -i "C:/Users/richa/.ssh/id_ed25519.ppk" -batch \
localfile sauer@10.0.2.1:/remote/path
This is also the workaround when a remote command needs literal quotes or
braces — PowerShell + plink eats them. Write the payload to a local file,
pscp it across, then have plink consume it (e.g. curl --data-binary @file).
"Ubuntu Server Mode"
When the user says "Ubuntu Server Mode" (or "server mode"), Claude treats
every shell command as if it were running on 10.0.2.1 as sauer — wrap each
command with the plink invocation transparently and follow server-side
conventions (sudo docker compose, Caddy reload paths, etc.). The server has
its own memory at ~/.claude/projects/-home-sauer/memory/MEMORY.md — read
that index before making changes. Stay in this mode until told to exit
("back to local", "exit server mode").
Notifications (server side)
claude-notify "message" # send to Telegram bridge
claude-inbox --pop # read responses