Develop Directly on a Server with VS Code Remote SSH
10 Apr 2026Syncing a repo to a remote box with rsync on a watch loop, editing locally, then re-syncing is slower and flakier than just editing the files where they live. VS Code’s Remote-SSH extension runs the entire editor backend on the server and only ships the UI to your laptop.
Install and connect
Install the Remote - SSH extension from the VS Code marketplace. Then:
Cmd/Ctrl + Shift + P→ Remote-SSH: Connect to Host- Enter
user@your-server-ip, or pick from your~/.ssh/configif you already have hosts defined there. - VS Code opens a new window, installs a small server component on the remote box automatically, and reconnects your terminal, file explorer, and extensions to run against the remote filesystem.
Once connected, code . inside a project directory on the server, or File → Open Folder, opens it exactly like a local project — except every file read, every save, every terminal command runs on the server, with zero sync lag.
Set up your SSH config first, not the extension’s prompt
# ~/.ssh/config
Host prod-app
HostName 203.0.113.12
User deploy
IdentityFile ~/.ssh/id_ed25519
ForwardAgent yes
Do this before opening Remote-SSH. The extension reads ~/.ssh/config directly, so prod-app shows up as a one-click host instead of you retyping the IP and key path every time.
ForwardAgent yes matters if the remote box needs to authenticate against a private git remote — it forwards your local SSH agent so the server can git pull a private repo without a key sitting on the server itself.
Performance: what’s fast and what isn’t
| Operation | Speed |
|---|---|
| Editing, IntelliSense, search | Fast — runs entirely on the remote |
| Extensions (linters, language servers) | Fast — installed and running remotely |
| Terminal | Native remote shell, no lag |
Opening a huge node_modules-heavy folder |
Slow the first time — file watcher indexing |
| git operations | As fast as the server’s own connection to the remote |
The one place this genuinely gets slow is a repo with a massive node_modules or .git directory on first open, while VS Code’s file watcher walks it. Add heavy directories to files.watcherExclude in remote settings to skip them.
Extensions run twice — know which side installs what
Some extensions are UI-only (themes, keybindings) and stay local. Most functional ones — language servers, linters, Docker tooling — install a remote copy on the server the first time you use them in a Remote-SSH window. This means your first connection to a new server re-triggers extension installs, which takes a minute or two. After that it’s cached.
Port forwarding, so localhost:3000 on your laptop hits the server
Open the Ports tab in the bottom panel, click Forward a Port, enter the port your app listens on remotely. VS Code tunnels it over the same SSH connection — no separate ssh -L command needed, and it survives editor restarts within the session.
When Remote-SSH beats a local clone + rsync
- The server has resources (GPU, large dataset, production-like environment) your laptop doesn’t.
- You’re debugging something that only reproduces on that specific box.
- Multiple people need to work against the same live environment without merge conflicts from parallel local clones.
When it doesn’t
If you’re offline often, or the server is unreliable, you lose editing entirely when the SSH connection drops — there’s no local fallback mid-session. For that workflow, a local clone with a fast rsync --delete on save (or just git push / git pull) is more resilient, even if it’s less immediate.
The setting that avoids the most friction
"remote.SSH.connectTimeout": 60
Default timeout is short enough that a server with a slow SSH banner or MOTD script causes a “could not establish connection” error that has nothing to do with your actual network. Bump it before you start debugging the wrong thing.