remote-development.md

  1---
  2title: Remote Development - Zed
  3description: Edit code on remote servers with Zed. Local UI performance with remote language servers, terminals, and tasks over SSH.
  4---
  5
  6# Remote Development
  7
  8Remote Development lets you edit code on a remote server while running Zed locally. The UI stays responsive because it runs on your machine, while language servers, tasks, and terminals run on the server.
  9
 10## Overview
 11
 12Remote development requires two computers, your local machine that runs the Zed UI and the remote server which runs a Zed headless server. The two communicate over SSH, so you will need to be able to SSH from your local machine into the remote server to use this feature.
 13
 14![Architectural overview of Zed Remote Development](https://zed.dev/img/remote-development/diagram.png)
 15
 16On your local machine, Zed runs its UI, talks to language models, uses Tree-sitter to parse and syntax-highlight code, and store unsaved changes and recent projects. The source code, language servers, tasks, and the terminal all run on the remote server. [AI features](./ai/overview.md) work in remote sessions, including the Agent Panel and Inline Assistant.
 17
 18> **Note:** The original version of remote development sent traffic via Zed's servers. As of Zed v0.157 you can no-longer use that mode.
 19
 20## Setup
 21
 221. Download and install the latest [Zed](https://zed.dev/releases). You need at least Zed v0.159.
 231. Use {#kb projects::OpenRemote} to open the "Remote Projects" dialog.
 241. Click "Connect New Server" and enter the command you use to SSH into the server. See [Supported SSH options](#supported-ssh-options) for options you can pass.
 251. Your local machine will attempt to connect to the remote server using the `ssh` binary on your path. Assuming the connection is successful, Zed will download the server on the remote host and start it.
 261. Once the Zed server is running, you will be prompted to choose a path to open on the remote server.
 27   > **Note:** Zed does not currently handle opening very large directories (for example, `/` or `~` that may have >100,000 files) very well. We are working on improving this, but suggest in the meantime opening only specific projects, or subfolders of very large mono-repos.
 28
 29For simple cases where you don't need any SSH arguments, you can run `zed ssh://[<user>@]<host>[:<port>]/<path>` to open a remote folder/file directly. If you'd like to hotlink into an SSH project, use a link of the format: `zed://ssh/[<user>@]<host>[:<port>]/<path>`.
 30
 31## Supported platforms
 32
 33The remote machine must be able to run Zed's server. The following platforms should work, though note that we have not exhaustively tested every Linux distribution:
 34
 35- macOS Catalina or later (Intel or Apple Silicon)
 36- Linux (x86_64 or arm64, we do not yet support 32-bit platforms)
 37- Windows is not yet supported as a remote server, but Windows can be used as a local machine to connect to remote servers.
 38
 39## Configuration
 40
 41The list of remote servers is stored in your settings file {#kb zed::OpenSettings}. You can edit this list using the Remote Projects dialog {#kb projects::OpenRemote}, which provides some robustness - for example it checks that the connection can be established before writing it to the settings file.
 42
 43```json [settings]
 44{
 45  "ssh_connections": [
 46    {
 47      "host": "192.168.1.10",
 48      "projects": [{ "paths": ["~/code/zed/zed"] }]
 49    }
 50  ]
 51}
 52```
 53
 54Zed shells out to the `ssh` on your path, and so it will inherit any configuration you have in `~/.ssh/config` for the given host. That said, if you need to override anything you can configure the following additional options on each connection:
 55
 56```json [settings]
 57{
 58  "ssh_connections": [
 59    {
 60      "host": "192.168.1.10",
 61      "projects": [{ "paths": ["~/code/zed/zed"] }],
 62      // any argument to pass to the ssh master process
 63      "args": ["-i", "~/.ssh/work_id_file"],
 64      "port": 22, // defaults to 22
 65      // defaults to your username on your local machine
 66      "username": "me"
 67    }
 68  ]
 69}
 70```
 71
 72There are two additional Zed-specific options per connection, `upload_binary_over_ssh` and `nickname`:
 73
 74```json [settings]
 75{
 76  "ssh_connections": [
 77    {
 78      "host": "192.168.1.10",
 79      "projects": [{ "paths": ["~/code/zed/zed"] }],
 80      // by default Zed will download the server binary from the internet on the remote.
 81      // When this is true, it'll be downloaded to your laptop and uploaded over SSH.
 82      // This is useful when your remote server has restricted internet access.
 83      "upload_binary_over_ssh": true,
 84      // Shown in the Zed UI to help distinguish multiple hosts.
 85      "nickname": "lil-linux"
 86    }
 87  ]
 88}
 89```
 90
 91If you use the command line to open a connection to a host by doing `zed ssh://192.168.1.10/~/.vimrc`, then extra options are read from your settings file by finding the first connection that matches the host/username/port of the URL on the command line.
 92
 93Additionally it's worth noting that while you can pass a password on the command line `zed ssh://user:password@host/~`, we do not support writing a password to your settings file. If you're connecting repeatedly to the same host, you should configure key-based authentication.
 94
 95## Remote Development on Windows (SSH)
 96
 97Zed on Windows supports SSH remoting and will prompt for credentials when needed.
 98
 99If you encounter authentication issues, confirm that your SSH key agent is running (e.g., ssh-agent or your Git client's agent) and that ssh.exe is on PATH.
100
101### Troubleshooting SSH on Windows
102
103When prompted for credentials, use the graphical askpass dialog. If it doesn't appear, check for credential manager conflicts and that GUI prompts aren't blocked by your terminal.
104
105## WSL Support
106
107Zed supports opening folders inside of WSL natively on Windows.
108
109### Opening a local folder in WSL
110
111To open a local folder inside a WSL container, use the `projects: open in wsl` action and select the folder you want to open. You will be presented with a list of available WSL distributions to open the folder in.
112
113### Opening a folder already in WSL
114
115To open a folder that's already located inside of a WSL container, use the `projects: open wsl` action and select the WSL distribution. The distribution will be added to the `Remote Projects` window where you will be able to open the folder.
116
117## Port forwarding
118
119If you'd like to be able to connect to ports on your remote server from your local machine, you can configure port forwarding in your settings file. This is particularly useful for developing websites so you can load the site in your browser while working.
120
121```json [settings]
122{
123  "ssh_connections": [
124    {
125      "host": "192.168.1.10",
126      "port_forwards": [{ "local_port": 8080, "remote_port": 80 }]
127    }
128  ]
129}
130```
131
132This will cause requests from your local machine to `localhost:8080` to be forwarded to the remote machine's port 80. Under the hood this uses the `-L` argument to ssh.
133
134By default these ports are bound to localhost, so other computers in the same network as your development machine cannot access them. You can set the local_host to bind to a different interface, for example, 0.0.0.0 will bind to all local interfaces.
135
136```json [settings]
137{
138  "ssh_connections": [
139    {
140      "host": "192.168.1.10",
141      "port_forwards": [
142        {
143          "local_port": 8080,
144          "remote_port": 80,
145          "local_host": "0.0.0.0"
146        }
147      ]
148    }
149  ]
150}
151```
152
153These ports also default to the `localhost` interface on the remote host. If you need to change this, you can also set the remote host:
154
155```json [settings]
156{
157  "ssh_connections": [
158    {
159      "host": "192.168.1.10",
160      "port_forwards": [
161        {
162          "local_port": 8080,
163          "remote_port": 80,
164          "remote_host": "docker-host"
165        }
166      ]
167    }
168  ]
169}
170```
171
172## Zed settings
173
174When opening a remote project there are three relevant settings locations:
175
176- The local Zed settings (in `~/.zed/settings.json` on macOS or `~/.config/zed/settings.json` on Linux) on your local machine.
177- The server Zed settings (in the same place) on the remote server.
178- The project settings (in `.zed/settings.json` or `.editorconfig` of your project)
179
180Both the local Zed and the server Zed read the project settings, but they are not aware of the other's main `settings.json`.
181
182Which settings file you should use depends on the kind of setting you want to make:
183
184- Project settings should be used for things that affect the project: indentation settings, which formatter / language server to use, etc.
185- Server settings should be used for things that affect the server: paths to language servers, proxy settings, etc.
186- Local settings should be used for things that affect the UI: font size, etc.
187
188In addition any extensions you have installed locally will be propagated to the remote server. This means that language servers, etc. will run correctly.
189
190## Proxy Configuration
191
192The remote server will not use your local machine's proxy configuration because they may be under different network policies. If your remote server requires a proxy to access the internet, you must configure it on the remote server itself.
193
194In most cases, your remote server will already have proxy environment variables configured. Zed will automatically use them when downloading language servers, communicating with LLM models, etc.
195
196If needed, you can set these environment variables in the server's shell configuration (e.g., `~/.bashrc`):
197
198```bash
199export http_proxy="http://proxy.example.com:8080"
200export https_proxy="http://proxy.example.com:8080"
201export no_proxy="localhost,127.0.0.1"
202```
203
204Alternatively, you can configure the proxy in the remote machine's `~/.config/zed/settings.json` (Linux) or `~/.zed/settings.json` (macOS):
205
206```json
207{
208  "proxy": "http://proxy.example.com:8080"
209}
210```
211
212See the [proxy documentation](./reference/all-settings.md#network-proxy) for supported proxy types and additional configuration options.
213
214## Initializing the remote server
215
216Once you provide the SSH options, Zed shells out to `ssh` on your local machine to create a ControlMaster connection with the options you provide.
217
218Any prompts that SSH needs will be shown in the UI, so you can verify host keys, type key passwords, etc.
219
220Once the master connection is established, Zed will check to see if the remote server binary is present in `~/.zed_server` on the remote, and that its version matches the current version of Zed that you're using.
221
222If it is not there or the version mismatches, Zed will try to download the latest version. By default, it will download from `https://zed.dev` directly, but if you set: `{"upload_binary_over_ssh":true}` in your settings for that server, it will download the binary to your local machine and then upload it to the remote server.
223
224If you'd like to maintain the server binary yourself you can. You can either download our prebuilt versions from [GitHub](https://github.com/zed-industries/zed/releases), or [build your own](https://zed.dev/docs/development) with `cargo build -p remote_server --release`. If you do this, you must upload it to `~/.zed_server/zed-remote-server-{RELEASE_CHANNEL}-{VERSION}` on the server, for example `~/.zed_server/zed-remote-server-stable-0.217.3+stable.105.80433cb239e868271457ac376673a5f75bc4adb1`. The version must exactly match the version of Zed itself you are using.
225
226## Maintaining the SSH connection
227
228Once the server is initialized. Zed will create new SSH connections (reusing the existing ControlMaster) to run the remote development server.
229
230Each connection tries to run the development server in proxy mode. This mode will start the daemon if it is not running, and reconnect to it if it is. This way when your connection drops and is restarted, you can continue to work without interruption.
231
232In the case that reconnecting fails, the daemon will not be re-used. That said, unsaved changes are by default persisted locally, so that you do not lose work. You can always reconnect to the project at a later date and Zed will restore unsaved changes.
233
234If you are struggling with connection issues, you should be able to see more information in the Zed log `cmd-shift-p Open Log`. If you are seeing things that are unexpected, please file a [GitHub issue](https://github.com/zed-industries/zed/issues/new) or reach out in the #remoting-feedback channel in the [Zed Discord](https://zed.dev/community-links).
235
236## Supported SSH Options
237
238Under the hood, Zed shells out to the `ssh` binary to connect to the remote server. We create one SSH control master per project, and then use that to multiplex SSH connections for the Zed protocol itself, any terminals you open and tasks you run. We read settings from your SSH config file, but if you want to specify additional options to the SSH control master you can configure Zed to set them.
239
240When typing in the "Connect New Server" dialog, you can use bash-style quoting to pass options containing a space. Once you have created a server it will be added to the `"ssh_connections": []` array in your settings file. You can edit the settings file directly to make changes to SSH connections.
241
242Supported options:
243
244- `-p` / `-l` - these are equivalent to passing the port and the username in the host string.
245- `-L` / `-R` for port forwarding
246- `-i` - to use a specific key file
247- `-o` - to set custom options
248- `-J` / `-w` - to proxy the SSH connection
249- `-F` for specifying an `ssh_config`
250- And also... `-4`, `-6`, `-A`, `-B`, `-C`, `-D`, `-I`, `-K`, `-P`, `-X`, `-Y`, `-a`, `-b`, `-c`, `-i`, `-k`, `-l`, `-m`, `-o`, `-p`, `-w`, `-x`, `-y`
251
252Note that we deliberately disallow some options (for example `-t` or `-T`) that Zed will set for you.
253
254## Known Limitations
255
256- You can't open files from the remote Terminal by typing the `zed` command.
257
258## Feedback
259
260Please join the #remoting-feedback channel in the [Zed Discord](https://zed.dev/community-links).