docs/src/configuring-languages.md
Zed's language support is built on two technologies:
This page covers language-specific settings, file associations, language server configuration, formatting, linting, and syntax highlighting.
For a list of supported languages, see Supported Languages. To add support for new languages, see Language Extensions.
Zed allows you to override global settings for individual languages. These custom configurations are defined in your settings.json file under the languages key.
Here's an example of language-specific settings:
"languages": {
"Python": {
"tab_size": 4,
"formatter": "language_server",
"format_on_save": "on"
},
"JavaScript": {
"tab_size": 2,
"formatter": {
"external": {
"command": "prettier",
"arguments": ["--stdin-filepath", "{buffer_path}"]
}
}
}
}
You can customize a wide range of settings for each language, including:
tab_size: The number of spaces for each indentation levelformatter: The tool used for code formattingformat_on_save: Whether to automatically format code when savingenable_language_server: Toggle language server supporthard_tabs: Use tabs instead of spaces for indentationpreferred_line_length: The recommended maximum line lengthsoft_wrap: How to wrap long lines of codeshow_completions_on_input: Whether or not to show completions as you typeshow_completion_documentation: Whether to display inline and alongside documentation for items in the completions menucolorize_brackets: Whether to use tree-sitter bracket queries to detect and colorize the brackets in the editor (also known as "rainbow brackets")These settings allow you to maintain specific coding styles across different languages and projects.
Zed automatically detects file types based on their extensions, but you can customize these associations to fit your workflow.
To set up custom file associations, use the file_types setting in your settings.json:
"file_types": {
"C++": ["c"],
"TOML": ["MyLockFile"],
"Dockerfile": ["Dockerfile*"]
}
This configuration tells Zed to:
.c files as C++ instead of CYou can use glob patterns for more flexible matching, allowing you to handle complex naming conventions in your projects.
Language servers are a crucial part of Zed's intelligent coding features, providing capabilities like auto-completion, go-to-definition, and real-time error checking.
Language servers implement the Language Server Protocol (LSP), which standardizes communication between the editor and language-specific tools. This allows Zed to support advanced features for multiple programming languages without implementing each feature separately.
Some key features provided by language servers include:
Zed simplifies language server management for users:
Automatic Download: When you open a file with a matching file type, Zed automatically downloads the appropriate language server. Zed may prompt you to install an extension for known file types.
Storage Location:
~/Library/Application Support/Zed/languages$XDG_DATA_HOME/zed/languages, $FLATPAK_XDG_DATA_HOME/zed/languages, or $HOME/.local/share/zed/languagesAutomatic Updates: Zed keeps your language servers up-to-date, ensuring you always have the latest features and improvements.
Some languages in Zed offer multiple language server options. You might have multiple extensions installed that bundle language servers targeting the same language, potentially leading to overlapping capabilities. To ensure you get the functionality you prefer, Zed allows you to prioritize which language servers are used and in what order.
You can specify your preference using the language_servers setting:
"languages": {
"PHP": {
"language_servers": ["intelephense", "!phpactor", "!phptools", "..."]
}
}
In this example:
intelephense is set as the primary language server.phpactor and phptools are disabled (note the ! prefix)."..." expands to the rest of the language servers registered for PHP that are not already listed.The "..." entry acts as a wildcard that includes any registered language server you haven't explicitly mentioned. Servers you list by name keep their position, and "..." fills in the remaining ones at that point in the list. Servers prefixed with ! are excluded entirely. This means that if a new language server extension is installed or a new server is registered for a language, "..." will automatically include it. If you want full control over which servers are enabled, omit "..." — only the servers you list by name will be used.
Suppose you're working with Ruby. The default configuration is:
{
"language_servers": [
"solargraph",
"!ruby-lsp",
"!rubocop",
"!sorbet",
"!steep",
"!kanayago",
"..."
]
}
When you override language_servers in your settings, your list replaces the default entirely. This means default-disabled servers like kanayago will be re-enabled by "..." unless you explicitly disable them again.
| Configuration | Result |
|---|---|
["..."] | solargraph, ruby-lsp, rubocop, sorbet, steep, kanayago |
["ruby-lsp", "..."] | ruby-lsp, solargraph, rubocop, sorbet, steep, kanayago |
["ruby-lsp", "!solargraph", "!kanayago", "..."] | ruby-lsp, rubocop, sorbet, steep |
["ruby-lsp", "solargraph"] | ruby-lsp, solargraph |
Note: In the first example,
"..."includeskanayagoeven though it is disabled by default. The override replaced the default list, so the"!kanayago"entry is no longer present. To keep it disabled, you must include"!kanayago"in your configuration.
Some language servers need to be configured with a current "toolchain", which is an installation of a specific version of a programming language compiler or/and interpreter, which can possibly include a full set of dependencies of a project.
An example of what Zed considers a toolchain is a virtual environment in Python.
Not all languages in Zed support toolchain discovery and selection, but for those that do, you can specify the toolchain from a toolchain picker (via {#action toolchain::Select}). To learn more about toolchains in Zed, see toolchains.
When configuring language servers in your settings.json, autocomplete suggestions include all available LSP adapters recognized by Zed, not only those currently active for loaded languages. This helps you discover and configure language servers before opening files that use them.
Many language servers accept custom configuration options. You can set these in the lsp section of your settings.json:
"lsp": {
"rust-analyzer": {
"initialization_options": {
"check": {
"command": "clippy"
}
}
}
}
This example configures the Rust Analyzer to use Clippy for additional linting when saving files.
When configuring language server options in Zed, it's important to use nested objects rather than dot-delimited strings. This is particularly relevant when working with more complex configurations. Let's look at a real-world example using the TypeScript language server:
Suppose you want to configure the following settings for TypeScript:
Here's how you would structure these settings in Zed's settings.json:
"lsp": {
"typescript-language-server": {
"initialization_options": {
// These are not supported (VSCode dotted style):
// "preferences.strictNullChecks": true,
// "preferences.target": "ES2020"
//
// These is correct (nested notation):
"preferences": {
"strictNullChecks": true,
"target": "ES2020"
},
}
}
}
Depending on how a particular language server is implemented, they may depend on different configuration options, both specified in the LSP.
Sent once during language server startup, requires server's restart to reapply changes.
For example, rust-analyzer and clangd rely on this way of configuring only.
"lsp": {
"rust-analyzer": {
"initialization_options": {
"checkOnSave": false
}
}
}
May be queried by the server multiple times. Most of the servers would rely on this way of configuring only.
"lsp": {
"tailwindcss-language-server": {
"settings": {
"tailwindCSS": {
"emmetCompletions": true,
},
}
}
}
Apart of the LSP-related server configuration options, certain servers in Zed allow configuring the way binary is launched by Zed.
Language servers are automatically downloaded or launched if found in your path, if you wish to specify an explicit alternate binary you can specify that in settings:
"lsp": {
"rust-analyzer": {
"binary": {
// Whether to fetch the binary from the internet, or attempt to find locally.
"ignore_system_version": false,
"path": "/path/to/langserver/bin",
"arguments": ["--option", "value"],
"env": {
"FOO": "BAR"
}
}
}
}
You can toggle language server support globally or per-language:
"languages": {
"Markdown": {
"enable_language_server": false
}
}
This disables the language server for Markdown files, which can be useful for performance in large documentation projects. You can configure this globally in your ~/.config/zed/settings.json or inside a .zed/settings.json in your project directory.
Zed provides support for code formatting and linting to maintain consistent code style and catch potential issues early.
Zed supports both built-in and external formatters. See formatter docs for more. You can configure formatters globally or per-language in your settings.json:
"languages": {
"JavaScript": {
"formatter": {
"external": {
"command": "prettier",
"arguments": ["--stdin-filepath", "{buffer_path}"]
}
},
"format_on_save": "on"
},
"Rust": {
"formatter": "language_server",
"format_on_save": "on"
}
}
This example uses Prettier for JavaScript and the language server's formatter for Rust, both set to format on save.
To disable formatting for a specific language:
"languages": {
"Markdown": {
"format_on_save": "off"
}
}
Linting in Zed is typically handled by language servers. Many language servers allow you to configure linting rules:
"lsp": {
"eslint": {
"settings": {
"codeActionOnSave": {
"rules": ["import/order"]
}
}
}
}
This configuration sets up ESLint to organize imports on save for JavaScript files.
To run linter fixes automatically on save:
"languages": {
"JavaScript": {
"formatter": {
"code_action": "source.fixAll.eslint"
}
}
}
Zed allows you to run both formatting and linting on save. Here's an example that uses Prettier for formatting and ESLint for linting JavaScript files:
"languages": {
"JavaScript": {
"formatter": [
{
"code_action": "source.fixAll.eslint"
},
{
"external": {
"command": "prettier",
"arguments": ["--stdin-filepath", "{buffer_path}"]
}
}
],
"format_on_save": "on"
}
}
If you encounter issues with formatting or linting:
zed: open log).eslintrc, .prettierrc)Zed offers customization options for syntax highlighting and themes, allowing you to tailor the visual appearance of your code.
Zed uses Tree-sitter grammars for syntax highlighting. Override the default highlighting using the theme_overrides setting.
This example makes comments italic and changes the color of strings:
"theme_overrides": {
"One Dark": {
"syntax": {
"comment": {
"font_style": "italic"
},
"string": {
"color": "#00AA00"
}
}
}
}
Change your theme:
settings.json:"theme": {
"mode": "dark",
"dark": "One Dark",
"light": "GitHub Light"
}
Create custom themes by creating a JSON file in ~/.config/zed/themes/. Zed will automatically detect and make available any themes in this directory.
Zed supports theme extensions. Browse and install theme extensions from the Extensions panel ({#kb zed::Extensions}).
To create your own theme extension, refer to the Developing Theme Extensions guide.
Semantic tokens provide richer syntax highlighting by using type and scope information from language servers. Enable them with the semantic_tokens setting:
"semantic_tokens": "combined"
"off" — Tree-sitter highlighting only (default)"combined" — LSP semantic tokens overlaid on tree-sitter"full" — LSP semantic tokens replace tree-sitter entirelyYou can customize token colors and styles through global_lsp_settings.semantic_token_rules in your settings.
→ Semantic Tokens documentation
Inlay hints provide additional information inline in your code, such as parameter names or inferred types. Configure inlay hints in your settings.json:
"inlay_hints": {
"enabled": true,
"show_type_hints": true,
"show_parameter_hints": true,
"show_other_hints": true
}
For language-specific inlay hint settings, refer to the documentation for each language.
Code actions provide quick fixes and refactoring options. Access code actions using the editor: Toggle Code Actions command or by clicking the lightbulb icon that appears next to your cursor when actions are available.
Use these commands to navigate your codebase:
editor: Go to Definition (<kbd>f12|f12</kbd>)editor: Go to Type Definition (<kbd>cmd-f12|ctrl-f12</kbd>)editor: Find All References (<kbd>shift-f12|shift-f12</kbd>)To rename a symbol across your project:
editor: Rename Symbol command (<kbd>f2|f2</kbd>)These features depend on the capabilities of the language server for each language.
When renaming a symbol that spans multiple files, Zed will open a preview in a multibuffer. This allows you to review all the changes across your project before applying them. To confirm the rename, simply save the multibuffer. If you decide not to proceed with the rename, you can undo the changes or close the multibuffer without saving.
Use the editor: Hover command to display information about the symbol under the cursor. This often includes type information, documentation, and links to relevant resources.
The {#action project_symbols::Toggle} command allows you to search for symbols (functions, classes, variables) across your entire project. This is useful for quickly navigating large codebases.
Zed provides intelligent code completion suggestions as you type. You can manually trigger completion with the editor: Show Completions command. Use <kbd>tab|tab</kbd> or <kbd>enter|enter</kbd> to accept suggestions.
Language servers provide real-time diagnostics (errors, warnings, hints) as you code. View all diagnostics for your project using the {#action diagnostics::Deploy} command.