Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions mkdocs/docs/concepts/dev-environments.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ To connect via SSH, use: `ssh vscode`

`dstack apply` automatically provisions an instance and sets up an IDE on it.

The `ide` property supports `vscode`, `cursor`, `windsurf`, and `zed`.

??? info "SSH-only"
The `ide` property is optional. If omitted, no IDE is pre-installed, but the dev environment
is still accessible via SSH:
Expand Down
4 changes: 2 additions & 2 deletions src/dstack/_internal/core/models/configurations.py
Original file line number Diff line number Diff line change
Expand Up @@ -685,9 +685,9 @@ def check_image_or_commands_present(cls, values):

class DevEnvironmentConfigurationParams(CoreModel):
ide: Annotated[
Optional[Union[Literal["vscode"], Literal["cursor"], Literal["windsurf"]]],
Optional[Union[Literal["vscode"], Literal["cursor"], Literal["windsurf"], Literal["zed"]]],
Field(
description="The IDE to pre-install. Supported values include `vscode`, `cursor`, and `windsurf`. Defaults to no IDE (SSH only)"
description="The IDE to pre-install. Supported values include `vscode`, `cursor`, `windsurf`, and `zed`. Defaults to no IDE (SSH only)"
),
] = None
version: Annotated[
Expand Down
4 changes: 3 additions & 1 deletion src/dstack/_internal/server/services/ides/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
from dstack._internal.server.services.ides.cursor import CursorDesktop
from dstack._internal.server.services.ides.vscode import VSCodeDesktop
from dstack._internal.server.services.ides.windsurf import WindsurfDesktop
from dstack._internal.server.services.ides.zed import ZedDesktop

_IDELiteral = Literal["vscode", "cursor", "windsurf"]
_IDELiteral = Literal["vscode", "cursor", "windsurf", "zed"]

_ide_literal_to_ide_class_map: dict[_IDELiteral, type[IDE]] = {
"vscode": VSCodeDesktop,
"cursor": CursorDesktop,
"windsurf": WindsurfDesktop,
"zed": ZedDesktop,
}


Expand Down
19 changes: 19 additions & 0 deletions src/dstack/_internal/server/services/ides/zed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from typing import Optional

from dstack._internal.server.services.ides.base import IDE


class ZedDesktop(IDE):
name = "Zed"
url_scheme = "zed"

def get_install_commands(
self, version: Optional[str] = None, extensions: Optional[list[str]] = None
) -> list[str]:
# We don't need to pre-install any extensions for Zed so we let it
# auto-install the remote server into ~/.zed_server on the first SSH connect,
# downloading the binary that matches the connecting Zed client version.
return []

def get_url(self, authority: str, working_dir: str) -> str:
return f"zed://ssh/{authority}{working_dir}"
10 changes: 10 additions & 0 deletions src/tests/_internal/core/models/test_configurations.py
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,16 @@ def test_cursor_version_not_validated(self):
assert params.ide == "cursor"
assert params.version == "0.40.0"

def test_zed_ide_allowed(self):
params = DevEnvironmentConfigurationParams(ide="zed")
assert params.ide == "zed"
assert params.version is None

def test_zed_version_not_validated(self):
params = DevEnvironmentConfigurationParams(ide="zed", version="0.100.0")
assert params.ide == "zed"
assert params.version == "0.100.0"

def test_ide_optional(self):
params = DevEnvironmentConfigurationParams()
assert params.ide is None
Expand Down
Loading