Zed: Difference between revisions

Mention home-manager remote server option
Layer-09 (talk | contribs)
mNo edit summary
 
(8 intermediate revisions by 5 users not shown)
Line 1: Line 1:
<languages/>
{{infobox application
  |name=Zed
  |image=Zed_Editor_Logo.png
  |type=Source-code Editor
  |developer=Zed Industries
  |predecessor=Atom
  |status=Active
  |license=[https://www.gnu.org/licenses/agpl-3.0.html AGPL], [https://www.gnu.org/licenses/gpl-3.0.html GPL], [https://www.apache.org/licenses/LICENSE-2.0 Apache License]
  |os=Cross-platform (Linux, macOS, Windows)
  |platform=Desktop
  |programmingLanguage=Rust
  |website=[https://zed.dev zed.dev]
  |github=zed-industries/zed
  |bugTracker=[https://github.com/zed-industries/zed/issues GitHub Issues]
  |documentation=[https://zed.dev/docs Zed Documentation]
}}
<translate>
<!--T:1-->
[https://zed.dev Zed]<ref>Zed Industries, "Zed", Official Website, Accessed October 2025. https://zed.dev</ref> is a collaborative, GPU-accelerated text editor developed by Zed Industries. It combines fast local editing with real-time multiplayer features and ships with batteries-included tooling for popular programming languages.
</translate>
<translate>
<!--T:2-->
The editor provides native builds for Linux, including Nixpkgs packages and a reproducible flake. Hardware acceleration requires a GPU with Vulkan support; systems without Vulkan can fall back to emulation via tools such as [https://github.com/nix-community/nixGL nixGL].<ref>Zed Industries, "Linux", Zed Documentation, Accessed October 2025. https://zed.dev/docs/linux</ref>
</translate>


[https://zed.dev/ Zed] is a graphical text editor focusing on speed and collaborative editing.
<translate>
== Installation == <!--T:3-->


Its Linux support is fairly recent, the NixOS support even more so.
==== Shell ==== <!--T:4-->
</translate>
{{code|lang=bash|line=no|1=$ nix-shell -p zed-editor}}
<translate>
<!--T:5-->
The <code>zed-editor</code> package is available in Nixpkgs from channel 24.11 onward. The command above provides <code>zed-editor</code> in the current shell session without modifying any configuration files.


== Installation ==
<!--T:6-->
The package zed-editor is available only from channel 24.11 onward.
The package installs both desktop launchers and a CLI entry point aliased to <code>zeditor</code>, mirroring the upstream binary name.


CLI support is installed and aliased to <code>zeditor</code>
==== System setup ==== <!--T:7-->
</translate>
{{code|lang=nix|line=no|1=# In /etc/nixos/configuration.nix
environment.systemPackages = [
  pkgs.zed-editor
];


== LSP Support ==
# In home-manager configuration (home.nix)
By default, Zed will try to download pre-built LSP servers in <code>~/.local/share/zed/languages/</code>. This does not work for NixOS.
home.packages = [
  pkgs.zed-editor
];
}}
<translate>
<!--T:8-->
Rebuild your system or Home Manager profile to make Zed available persistently. On NixOS, run <code>sudo nixos-rebuild switch</code>; for Home Manager, run <code>home-manager switch</code>.


There's sadly no way to inject those from <code>$PATH</code> for now. Worse, the way to point to the language server is language-specific, there is no global configuration flag for now.
==== Flake ==== <!--T:9-->


The following sections contain some language-specific setup working on NixOS.
<!--T:10-->
Zed maintains an official flake for tracking the latest upstream build. This approach is useful if you need features that have not yet reached stable Nixpkgs.
</translate>
{{code|lang=nix|line=no|1=inputs.zed.url = "github:zed-industries/zed";


=== rust-analyzer ===
outputs = { self, nixpkgs, zed, ... }@inputs: let
Here, we'll assume rust-analyzer is globally installed in your system profile at <code>/run/current-system/sw/bin/rust-analyzer</code>. You may want to adapt this path in the following code snippet to something more relevant to your use case.
  system = "x86_64-linux";
  pkgs = import nixpkgs { inherit system; };
in {
  packages.${system}.zed-latest = zed.packages.${system}.default;
};}}
<translate>
<!--T:11-->
Build the flake package with <code>nix build .#zed-latest</code> or expose it in your configuration with the appropriate overlay.
</translate>
{{Warning|Zed requires hardware-accelerated Vulkan. On systems without supported drivers, use <code>nixGL</code> or home-manager's <code>nixGL.vulkan.enable {{=}} true;</code> to provide the necessary libraries.}}
<translate>
<!--T:12-->
Providing Vulkan through <code>nixGL</code> can be more consistent than relying on host distribution packages, especially on non-NixOS systems where Wayland and X11 stacks differ in their Vulkan capabilities.


Add the following snippet to your zed configuration file:<syntaxhighlight lang="json">
== Configuration == <!--T:13-->
"lsp": {
  "rust-analyzer": {
    "binary": {
      "path": "/run/current-system/sw/bin/rust-analyzer",
    },
  }
}
</syntaxhighlight>


== Remote Server ==
<!--T:14-->
When connecting to a remote server running NixOS, Zed will automatically upload a static server binary matching its version (provided and built by upstream Zed) and connect to it:
Zed stores its configuration in JSON files under <code>~/.config/zed</code>. Home Manager can manage these settings declaratively.


:<syntaxhighlight lang="console">
==== Basic ==== <!--T:15-->
➜  ~ ls .zed_server
</translate>
zed-remote-server-stable-0.169.2
{{code|lang=nix|line=no|1=programs.zed-editor = {
➜  ~ file .zed_server/zed-remote-server-stable-0.169.2
  enable = true;
.zed_server/zed-remote-server-stable-0.169.2: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), static-pie linked, BuildID[sha1]=b1ac2c83127e7a9a072840cd7c24d7d125c1b655, not stripped
  extensions = [ "nix" "toml" "rust" ];
➜  ~ ldd .zed_server/zed-remote-server-stable-0.169.2
  userSettings = {
statically linked
    theme = {
</syntaxhighlight>
      mode = "system";
      dark = "One Dark";
      light = "One Light";
    };
    hour_format = "hour24";
    vim_mode = true;
  };
};}}
<translate>
<!--T:16-->
The configuration above enables Zed via Home Manager, installs a small set of extensions, and synchronises the theme with the desktop appearance.
 
==== Advanced ==== <!--T:17-->
</translate>
{{code|lang=nix|line=no|1=
programs.zed-editor = {
  enable = true;


While this static binary works fine on NixOS, you may want to consider using the nixpkgs provided server instead if you have custom patches to apply or mistrust whatever binary upstream Zed is downloading to your server.
  # This populates the userSettings "auto_install_extensions"
  extensions = [ "nix" "toml" "elixir" "make" ];


The binary name of the <code>remote_server</code> output of the <code>zed-editor</code> package matches what Zed expects on the remote, meaning you can symlink <code>"${pkgs.zed-editor.remote_server}/bin"</code> to <code>~/.zed_server</code> on the remote host to make use of it. As an end user, you have to ensure the remote uses the same version of the zed-editor package as the local client.
  # Everything inside of these brackets are Zed options
  userSettings = {
    assistant = {
      enabled = true;
      version = "2";
      default_open_ai_model = null;


In home-manager, this can be used as follows:
      # Provider options:
      # - zed.dev models (claude-3-5-sonnet-latest) requires GitHub connected
      # - anthropic models (claude-3-5-sonnet-latest, claude-3-haiku-latest, claude-3-opus-latest) requires API_KEY
      # - copilot_chat models (gpt-4o, gpt-4, gpt-3.5-turbo, o1-preview) requires GitHub connected
      default_model = {
        provider = "zed.dev";
        model = "claude-3-5-sonnet-latest";
      };
 
      # inline_alternatives = [
      #  {
      #    provider = "copilot_chat";
      #    model = "gpt-3.5-turbo";
      #  }
      # ];
    };
 
    node = {
      path = lib.getExe pkgs.nodejs;
      npm_path = lib.getExe' pkgs.nodejs "npm";
    };


:<syntaxhighlight lang="nix">
    hour_format = "hour24";
{ pkgs, ... }:
    auto_update = false;
{
  home.file.".zed_server".source = "${pkgs.zed-editor.remote_server}/bin";
}
</syntaxhighlight>


If the version does not match, Zed will try to upload the binary itself (as the existing remote binary has a version-specific name), and in this particular example fail to do so because we symlinked <code>.zed_server</code> to a read-only directory in the Nix store.
    terminal = {
      alternate_scroll = "off";
      blinking = "off";
      copy_on_select = false;
      dock = "bottom";
      detect_venv = {
        on = {
          directories = [ ".env" "env" ".venv" "venv" ];
          activate_script = "default";
        };
      };
      env = {
        TERM = "alacritty";
      };
      font_family = "FiraCode Nerd Font";
      font_features = null;
      font_size = null;
      line_height = "comfortable";
      option_as_meta = false;
      button = false;
      shell = "system";
      # shell = {
      #  program = "zsh";
      # };
      toolbar = {
        title = true;
      };
      working_directory = "current_project_directory";
    };


Alternatively, you may choose to only symlink the binary and not the directory, so Zed will successfully fall back to its own binary upload if the remote package version does not match:
    lsp = {
      rust-analyzer = {
        binary = {
          # path = lib.getExe pkgs.rust-analyzer;
          path_lookup = true;
        };
      };


:<syntaxhighlight lang="nix">
      nix = {
{ pkgs, ... }:
        binary = {
let
          path_lookup = true;
  inherit (pkgs.zed-editor) version remote_server;
        };
  binary_name = "zed-remote-server-stable-${version}";
      };
in
{
  home.file.".zed_server/${binary_name}".source = "${remote_server}/bin/${binary_name}";
}
</syntaxhighlight>


A more convenient home-manager option that does the same exists as well:
      elixir-ls = {
        binary = {
          path_lookup = true;
        };
        settings = {
          dialyzerEnabled = true;
        };
      };
    };


:<syntaxhighlight lang="nix">
    languages = {
{
      "Elixir" = {
  programs.zed-editor = {
        language_servers = [ "!lexical" "elixir-ls" "!next-ls" ];
    enable = true;
        format_on_save = {
    installRemoteServer = true;
          external = {
  };
            command = "mix";
}
            arguments = [ "format" "--stdin-filename" "{buffer_path}" "-" ];
</syntaxhighlight>
          };
        };
      };


      "HEEX" = {
        language_servers = [ "!lexical" "elixir-ls" "!next-ls" ];
        format_on_save = {
          external = {
            command = "mix";
            arguments = [ "format" "--stdin-filename" "{buffer_path}" "-" ];
          };
        };
      };
    };


== Home manager support ==
    vim_mode = true;
Zed is supported by home-manager, this way you are able to make a reproducible Zed setup.


'''userSettings''' option will be translated directly to '''json''' file.
    # Tell Zed to use direnv and direnv can use a flake.nix environment
    load_direnv = "shell_hook";
    base_keymap = "VSCode";


note that home-manager configuration produces a '''read only `settings.json`''' this means some features which requires to write this file might not work. For example change model at runtime. Changing AI model at runtime tries to write in the configuration.
    theme = {
      mode = "system";
      light = "One Light";
      dark = "One Dark";
    };


you can see an example of the home-manager configuration.
    show_whitespaces = "all";
    ui_font_size = 16;
:<syntaxhighlight lang="nix">
    buffer_font_size = 16;
{pkgs, lib, ... }:
  };
};
}}
<translate>
<!--T:18-->
This example adds language servers to the FHS sandbox, enables the bundled assistant, configures the terminal, and ensures remote server binaries are provided declaratively.


{
<!--T:19-->
    programs.zed-editor = {
The <code>userSettings</code> and <code>userKeyMaps</code> options translate directly into JSON. The <code>extraPackages</code> option includes additional Nixpkgs in the FHS environment, useful for LSP servers (e.g., <code>pkgs.nixd</code>) or optional tools (e.g., <code>pkgs.shellcheck</code> for the Basher LSP).
        enable = true;
        extensions = ["nix" "toml" "elixir" "make"];


        ## everything inside of these brackets are Zed options.
<!--T:20-->
        userSettings = {
Home Manager renders <code>settings.json</code> as read-only, which prevents Zed's GUI from saving most preference changes, including AI provider selection. Plan to manage long-term settings declaratively or temporarily disable the module when editing interactively.


            assistant = {
<!--T:21-->
                enabled = true;
Only the initial extension list can be defined declaratively; additional extensions installed through the GUI are stored within Zed's writable data directories and do not appear in <code>userSettings</code>. This follows a similar model to VSCode, where extensions require external binaries downloaded at runtime.
                version = "2";
</translate>
                default_open_ai_model = null;
                ### PROVIDER OPTIONS
                ### zed.dev models { claude-3-5-sonnet-latest } requires github connected
                ### anthropic models { claude-3-5-sonnet-latest claude-3-haiku-latest claude-3-opus-latest  } requires API_KEY
                ### copilot_chat models { gpt-4o gpt-4 gpt-3.5-turbo o1-preview } requires github connected
                default_model = {
                    provider = "zed.dev";
                    model = "claude-3-5-sonnet-latest";
                };


                #                inline_alternatives = [
== LSP support ==
                #                    {
<translate>
                #                        provider = "copilot_chat";
<!--T:22-->
                #                        model = "gpt-3.5-turbo";
Zed downloads language servers into <code>~/.local/share/zed/languages/</code>, which is read-only on NixOS. Instead, use declarative methods to supply LSP binaries.
                #                    }
</translate>
                #                ];
<translate>
            };
<!--T:23-->
Check <strong>LSP Logs → Server Info</strong> to confirm which binaries are running. Prefer language servers packaged in Nixpkgs so that dependencies are resolved within the Nix store.
</translate>


            node = {
==== Nix-ld (recommended) ====
                path = lib.getExe pkgs.nodejs;
<translate>
                npm_path = lib.getExe' pkgs.nodejs "npm";
<!--T:24-->
            };
Enable [[FAQ#I've downloaded a binary, but I can't run it, what can I do?|<code>nix-ld</code>]] so prebuilt language servers can resolve dynamic libraries without wrapping.
</translate>


            hour_format = "hour24";
==== FHS wrapper ====
            auto_update = false;
<translate>
            terminal = {
<!--T:25-->
                alternate_scroll = "off";
Use <code>pkgs.zed-editor.fhsWithPackages</code> to extend the FHS environment with additional system libraries when a language server requires them.
                blinking = "off";
</translate>
                copy_on_select = false;
{{code|lang=nix|line=no|1=pkgs.zed-editor.fhsWithPackages (pkgs: with pkgs; [ openssl zlib ])}}
                dock = "bottom";
<translate>
                detect_venv = {
<!--T:26-->
                    on = {
Remember that language servers started inside the wrapper do not automatically inherit tools from ad-hoc shells; include every dependency declaratively.
                        directories = [".env" "env" ".venv" "venv"];
</translate>
                        activate_script = "default";
                    };
                };
                env = {
                    TERM = "alacritty";
                };
                font_family = "FiraCode Nerd Font";
                font_features = null;
                font_size = null;
                line_height = "comfortable";
                option_as_meta = false;
                button = false;
                shell = "system";
                #{
                #                    program = "zsh";
                #};
                toolbar = {
                    title = true;
                };
                working_directory = "current_project_directory";
            };


==== Bring your own LSP servers ====
<translate>
<!--T:27-->
Newer versions of Zed can detect LSP servers installed in <code>PATH</code> and prefer local versions over automatically downloaded ones. Install LSP servers globally or provide them through nix shell.
</translate>
<translate>
<!--T:28-->
Nixpkgs versions of tools may be required for development on NixOS, especially for the C/C++ ecosystem. Check <strong>LSP Logs → Server Info</strong> to see which binaries are running.
</translate>
<translate>
<!--T:29-->
If automatic detection doesn't work, specify the path manually in your Zed configuration:
</translate>
{{code|lang=json|line=no|1={
  "lsp": {
    "rust-analyzer": {
      "binary": {
        "path": "/run/current-system/sw/bin/rust-analyzer"
      }
    }
  }
}
}}
<translate>
<!--T:30-->
Adjust the path for each language server you manage. The example above assumes rust-analyzer is installed in your system profile.
</translate>
== Remote server ==
<translate>
<!--T:31-->
Zed uploads a versioned remote server binary to <code>~/.zed_server</code> on the target host. The Nixpkgs package exposes the matching binary via the <code>remote_server</code> output.
</translate>
<translate>
<!--T:32-->
When you connect to a remote machine, the client either downloads a matching server binary from upstream or pushes a local copy if <code>"upload_binary_over_ssh": true</code> is enabled. Connections fail if the versions diverge.
</translate>
{{code|lang=nix|line=no|1=home.file.".zed_server" = {
  source = "${pkgs.zed-editor.remote_server}/bin";
  recursive = true;
};}}
<translate>
<!--T:33-->
The <code>recursive = true;</code> setting keeps the directory writable while symlinking individual binaries, allowing Zed to add new versions when needed. This is necessary because the <code>~/.zed_server</code> folder is also used when external clients connect to the current system as a remote.
</translate>
<translate>
<!--T:34-->
Alternatively, use Home Manager's built-in option for simpler setup:
</translate>
{{code|lang=nix|line=no|1=programs.zed-editor = {
  enable = true;
  installRemoteServer = true;
};}}
<translate>
<!--T:35-->
To restrict remote clients to a specific server version, set <code>recursive = false;</code> to make the entire folder read-only. Zed refuses to connect if it cannot provision the required binary, so document the restriction for collaborators.
</translate>


== Tips and tricks ==


            lsp = {
==== Vulkan diagnostics ====
                rust-analyzer = {
{{code|lang=bash|line=no|1=$ vulkaninfo --summary}}
<translate>
<!--T:36-->
Run the command above to check your Vulkan support before launching Zed. Install <code>vulkan-tools</code> if the command is not available. On non-NixOS systems, you may need to wrap Zed with <code>nixGLVulkan</code> from the nixGL package.
</translate>


                    binary = {
==== Preinstall extensions ====
                        #                        path = lib.getExe pkgs.rust-analyzer;
{{code|lang=json|line=no|1={
                        path_lookup = true;
  "extensions": [
                    };
    "nix",
                };
    "toml",
                nix = {
    "elixir"
                    binary = {
  ]
                        path_lookup = true;
}
                    };
}}
                };
<translate>
<!--T:37-->
Declaratively listing extensions ensures they are installed automatically on new systems while still allowing additional extensions to be added interactively.
</translate>


                elixir-ls = {
==== Synchronise settings across machines ====
                    binary = {
<translate>
                        path_lookup = true;
<!--T:38-->
                    };
Store the entire <code>~/.config/zed</code> directory in a version-controlled dotfiles repo or manage it with Home Manager to keep settings consistent across hosts.
                    settings = {
</translate>
                        dialyzerEnabled = true;
                    };
                };
            };


== Troubleshooting ==


            languages = {
==== Zed fails to start without Vulkan ====
                "Elixir" = {
<translate>
                    language_servers = ["!lexical" "elixir-ls" "!next-ls"];
<!--T:39-->
                    format_on_save = {
If the GUI refuses to launch, confirm that <code>vulkan-tools</code> reports a working ICD. Use <code>nixGL</code> or vendor packages that supply Vulkan drivers for your GPU.
                        external = {
</translate>
                            command = "mix";
                            arguments = ["format" "--stdin-filename" "{buffer_path}" "-"];
                        };
                    };
                };
                "HEEX" = {
                    language_servers = ["!lexical" "elixir-ls" "!next-ls"];
                    format_on_save = {
                        external = {
                            command = "mix";
                            arguments = ["format" "--stdin-filename" "{buffer_path}" "-"];
                        };
                    };
                };
            };


            vim_mode = true;
==== Remote collaboration disconnects ====
            ## tell zed to use direnv and direnv can use a flake.nix enviroment.
<translate>
            load_direnv = "shell_hook";
<!--T:40-->
            base_keymap = "VSCode";
Ensure the remote server binary matches the client version. Re-run <code>home-manager switch</code> or update the symlink in <code>~/.zed_server</code> if the versions diverge after an update.
            theme = {
</translate>
                mode = "system";
                light = "One Light";
                dark = "One Dark";
            };
            show_whitespaces = "all" ;
            ui_font_size = 16;
            buffer_font_size = 16;


        };
==== Language server missing binaries ====
<translate>
<!--T:41-->
When Zed reports missing tools, add the required executables to <code>programs.zed-editor.extraPackages</code> or wrap the server using <code>pkgs.writeShellApplication</code>.
</translate>


    };
== See also ==
}
* <translate>
<!--T:42-->
[[Home Manager]] – Manage Zed configuration declaratively
</translate>
* <translate>
<!--T:43-->
[[Graphics#Vulkan]] – Set up Vulkan on NixOS systems
</translate>
* <translate>
<!--T:44-->
[https://search.nixos.org/options?query=zed-editor NixOS options search for Zed]
</translate>


</syntaxhighlight>
== References ==
<references/>


[[Category:Applications]]
[[Category:Applications]]
[[Category:Text Editor]]
[[Category:Text Editor]]