Skip to main content
  1. Blog/

Setup Neovim With Zig

·3 mins

Update: 25 May 2025 After trying many different setups, I’d recommend you not read any furthter and use kickstart.nvim. It is very simple, a near one shot setup and works out of the box. You may have to set your zls version separately sometimes if you run into issues, but overall, I highly recommend it for a quick and easy setup.

Video outlining the process: https://www.youtube.com/watch?v=m8C0Cq9Uv9o


Here is what I do to configure Neovim to work with Zig for syntax highlighting and the language server:

Skip to just the files

You will need the following: #

  • A MacOS device
  • Neovim >=0.8 installed
  • Zig installed
  • zls version that matches the Zig version above installed
  • tree-sitter-cli installed (can use homebrew: brew install tree-sitter)

Configuration: #

1. Install a Neovim package manager #

I used the lazy.nvim package manager for Neovim. Install it like this:

git clone --filter=blob:none https://github.com/folke/lazy.nvim.git ~/.local/share/nvim/lazy/lazy.nvim

Then we configure Neovim to use lazy.nvim. Edit the file ~/.config/nvim/init.lua and add:

local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({
    "git",
    "clone",
    "--filter=blob:none",
    "https://github.com/folke/lazy.nvim.git",
    lazypath,
  })
end
vim.opt.rtp:prepend(lazypath)

Restart Neovim to check if the installation succeeded. You should be able to bring up the lazy.nvim interface by typing :Lazy in Neovim. Exit it by using :q

2. Add the relevant plugins for Zig #

We are going to use the nvim-lspconfig to setup zls and tree-sitter for syntax highlighting. So let’s first install those as plugins from lazy.nvim.

Add these lines to your ~/.config/nvim/init.lua:

1
2
3
4
5
6
7
require("lazy").setup({
    { "neovim/nvim-lspconfig" },
    {
        "nvim-treesitter/nvim-treesitter",
        build = ":TSUpdate",
    },
})

Restart your Neovim and let the plugins get installed.

3. Configure the plugins #

We only need to setup nvim-lspconfig so create a directory called lua in your ~/.config/nvim directory. Create a file lsp.lua in that directory:

~/.config/nvim/lua/lsp.lua contents:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
local lspconfig = require("lspconfig")
lspconfig.zls.setup {
  cmd = { "zls" },
  filetypes = { "zig", "zir" },
  root_dir = lspconfig.util.root_pattern("build.zig", ".git") or vim.loop.cwd,
  single_file_support = true,
}

vim.api.nvim_create_autocmd("LspAttach", {
  callback = function(args)
    local opts = { buffer = args.buf }
    vim.keymap.set("n", "gd", vim.lsp.buf.definition, opts) -- Go to definition
    vim.keymap.set("n", "K", vim.lsp.buf.hover, opts)       -- Hover info
  end,
})

Next we have to edit our ~/.config/nvim/init.lua to use the plugins in neovim. Add the following to your init.lua:

require("lsp")

require("nvim-treesitter.configs").setup {
    ensure_installed = { "zig" },
    highlight = { enable = true },
}

Restart your Neovim if you had it open and you should be all set. Here’s the full contents of all files:

TL;DR Just the contents of the files: #

~/.config/nvim/init.lua:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({
    "git",
    "clone",
    "--filter=blob:none",
    "https://github.com/folke/lazy.nvim.git",
    lazypath,
  })
end
vim.opt.rtp:prepend(lazypath)

-- Setup plugins
require("lazy").setup({
    { "neovim/nvim-lspconfig" },
    {
        "nvim-treesitter/nvim-treesitter",
        build = ":TSUpdate",
    },
})

require("lsp")

require("nvim-treesitter.configs").setup {
    ensure_installed = { "zig" },
    highlight = { enable = true },
}

~/.config/nvim/lua/lsp.lua:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
local lspconfig = require("lspconfig")
lspconfig.zls.setup {
  cmd = { "zls" },
  filetypes = { "zig", "zir" },
  root_dir = lspconfig.util.root_pattern("build.zig", ".git") or vim.loop.cwd,
  single_file_support = true,
}

vim.api.nvim_create_autocmd("LspAttach", {
  callback = function(args)
    local opts = { buffer = args.buf }
    vim.keymap.set("n", "gd", vim.lsp.buf.definition, opts) -- Go to definition
    vim.keymap.set("n", "K", vim.lsp.buf.hover, opts)       -- Hover info
  end,
})