# roslyn.nvim: driving the Roslyn C# language server from Neovim

> roslyn.nvim is a Lua plugin that attaches Neovim to the open source Roslyn language server, the one behind the C# extension in Visual Studio Code, with Razor and CSHTML support added through co-hosting. It goes beyond what nvim-lspconfig offers for Roslyn by handling multiple solutions, broad root detection, source generated files and a shared daemon.

**seblyng/roslyn.nvim** — Roslyn LSP plugin for neovim

- Repository: https://github.com/seblyng/roslyn.nvim
- Stars: 938 · Forks: 63
- Language: Lua
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/seblyng-roslyn-nvim

## A maintained fork of an OmniSharp-era plugin

roslyn.nvim is a fork of the plugin by jmederosalvarado, and the README describes it as actively maintained and upgraded. The reason a fork was needed is the change in the language server itself. OmniSharp, the older C# language server, is described as discontinued, and Roslyn is the open source successor now used by the Visual Studio Code C# extension that ships with the standard C# Dev Kit. That matters for anyone whose editor setup predates the switch: the old server is not going to gain the diagnostic and code fix improvements that the new one gets. The plugin is written in Lua, the repository has no GitHub releases and no version tags to speak of, and the top level listing shows a conventional Neovim plugin layout with lsp, lua, plugin and test directories plus a Makefile and stylua and luacheck configuration.

## The requirements are specific and the versions are dated

The README lists three requirements: Neovim >= 0.12.0, a Roslyn language server of at least version 5.12.0-1.26453.19 downloaded locally, and the .NET SDK installed with the dotnet command available. The Neovim floor is high, and it means this plugin is not for an older installation without an upgrade. The server version requirement is stated with the same build string used to describe the daemon keepalive default, which suggests the plugin tracks a specific server generation rather than working with anything older. The dotnet requirement is not optional either, because the language server itself ships as a dotnet global tool. The plugin therefore assumes a machine that already has a .NET development environment, which is a fair assumption for a C# developer and a real obstacle for anyone who only wants to edit C# files.

## Multiple solutions, broad root detection and a target command

The README is explicit that roslyn is now part of nvim-lspconfig but that the built-in setup does not implement everything this plugin does. The extras are the interesting part. Support for multiple solutions means you can keep several solution files in one repository and switch between them. Broad root_dir detection means the plugin searches for solution files upward through parent directories when the broad_search option is set, rather than only looking inside the current project directory, which matters when a solution sits above the folder you happen to be editing in. The Roslyn target command switches between multiple solutions interactively. Two callbacks round out the configuration: choose_target receives the array of targets and returns the one to use, falling back to guessing when it returns nil, and ignore_target receives the selected target and returns a boolean saying whether to skip attaching to it. The README gives a concrete use for the second one, disabling a solution with a lot of .NET Framework code on mac. There is also a lock_target option that pins the solution to vim.g.roslyn_nvim_selected_solution after the first attach.

## Daemon mode shares one server across editors

The server is started in daemon mode, and the README explains what that means in practice: a single language server is shared between multiple clients, such as several Neovim instances or other editors on the same machine, rather than each instance starting its own dedicated server. Clients relay over named pipes, while solutions are still opened per client, so sharing the process does not mean sharing the workspace. The stated benefits are lower runtime overhead, shared metadata caches, reduced memory usage and faster startup. The lifecycle detail matters operationally: the daemon stays alive for 900 seconds after the last client disconnects, which is the default as of server version 5.12.0-1.26453.19. The keepalive is configurable through the ROSLYN_LANGUAGE_SERVER_DAEMON_KEEPALIVE environment variable, where -1 keeps the daemon alive forever and 0 exits it immediately. A daemon that outlives your editor by fifteen minutes is convenient when you switch projects quickly and slightly surprising when you go looking for a stray process.

## Getting a current language server build

The installation path for the server is where most of the friction sits, because the versions matter. The README says that MasonInstall roslyn-language-server installs from nuget.org, which is not necessarily up to date with the version used in VS Code, and it recommends a custom Mason registry instead:

```lua
require("mason").setup({
    registries = {
        "github:mason-org/mason-registry",
        "github:Crashdummyy/mason-registry",
    },
})
```

That registry publishes two packages, roslyn at the same version as in VS Code, and roslyn-nightly with bleeding edge features and potentially breaking changes. The manual route installs the server as a dotnet global tool, and the README recommends the Azure DevOps feed over nuget.org because the latter is not updated often while the former sees updates several times a day:

```bash
dotnet tool install -g roslyn-language-server --prerelease --source https://pkgs.dev.azure.com/azure-public/vside/_packaging/vs-impl/nuget/v3/index.json
```

The README also notes that any version before 5.8.0-1.26262.10 lacks Razor and Blazor support, and that updating works the same way as installing with the update verb.

## Razor support replaces a separate plugin, and tests need Neovim 0.12

The Razor and CSHTML support is the most recent headline feature and it arrived through co-hosting the language server, which the README says supersedes the older rzls.nvim plugin. If you used rzls.nvim, the instruction is to uninstall it and the rzls language server, since keeping both will leave two servers fighting over the same file types. The plugin itself is installed with your preferred package manager, and the lazy.nvim entry is short:

```lua
return {
    "seblyng/roslyn.nvim",
    ---@module 'roslyn.config'
    ---@type RoslynNvimConfig
    opts = {
        -- your configuration comes here; leave empty for default settings
    },
}
```

The configuration defaults include a filewatching option with three values, auto, roslyn and off, where roslyn turns off Neovim filewatching so the language server does the watching itself, and off is described as a hack to disable all filewatching if you notice performance problems. The repository ships a Makefile whose test target clones nvim-test and runs it against the plugin with the lua path set, and it pins the Neovim runner version to v0.12.1 for both the runner and the test version, which is consistent with the stated Neovim requirement.

## Conclusion

roslyn.nvim fits a C# developer on Neovim who wants the same language server Visual Studio Code uses, who works across several solutions in one repository, and who is willing to track server versions and keep the .NET SDK installed. It does not fit someone on a Neovim older than 0.12.0, and it does not fit a setup that cannot host a long-lived daemon process, since the server stays alive for 900 seconds after the last client disconnects by default. Verify first that the language server build you install matches what the C# extension ships, because the README notes the nuget.org copy is often behind and recommends the Azure DevOps feed, then confirm the broad_search behaviour matches your repository layout. The licence field on the repository says MIT, and the last push was on 2026-09-10.

## FAQ

### What are the requirements for roslyn.nvim?

Neovim >= 0.12.0, a Roslyn language server of at least version 5.12.0-1.26453.19 downloaded locally, and the .NET SDK installed with the dotnet command available, since the server is distributed as a dotnet global tool.

### How do I install the Roslyn language server?

Through Mason with MasonInstall roslyn-language-server, or manually as a dotnet global tool. The README recommends the Azure DevOps feed over nuget.org because nuget.org is not updated often, and any version before 5.8.0-1.26262.10 will not support Razor and Blazor.

### What does roslyn.nvim do that nvim-lspconfig does not?

The README says roslyn is now part of nvim-lspconfig but does not implement all of what this plugin does. The extras listed are support for multiple solutions, broad root_dir detection that searches for solutions upward in parent directories when broad_search is set, support for source generated files, and a Roslyn target command to switch between multiple solutions.

### Does roslyn.nvim support Razor and CSHTML files?

Yes. The README says Razor and CSHTML support was added through co-hosting and supersedes the older rzls.nvim plugin, so if you used rzls.nvim you should uninstall it and the rzls language server.

### How long does the Roslyn daemon stay alive?

It stays alive for 900 seconds after the last client disconnects, which is the default as of server version 5.12.0-1.26453.19. The ROSLYN_LANGUAGE_SERVER_DAEMON_KEEPALIVE environment variable changes this, with -1 keeping it alive forever and 0 exiting immediately.

## Sources

- [Issues](https://github.com/seblyng/roslyn.nvim/issues)
- [License: MIT](https://github.com/seblyng/roslyn.nvim/blob/main/LICENSE)
- [README](https://github.com/seblyng/roslyn.nvim/blob/main/README.md)
- [seblyng/roslyn.nvim on GitHub](https://github.com/seblyng/roslyn.nvim)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/seblyng-roslyn-nvim
