How do I set window-local and buffer-local options correctly in Neovim Lua config using vim.wo and vim.bo?
Answer
vim.wo.number = true / vim.bo.tabstop = 2
Explanation
Neovim's Lua API exposes three namespaces for setting options with the correct scope: vim.wo for window-local options, vim.bo for buffer-local options, and vim.o (or vim.go) for global options. Using the wrong namespace for an option either silently does nothing or sets the wrong scope.
How it works
vim.wo(window-local): options likenumber,relativenumber,signcolumn,wrap,foldlevelvim.bo(buffer-local): options liketabstop,shiftwidth,expandtab,filetype,readonlyvim.o(global): options likehidden,clipboard,termguicolors,mousevim.opt: a smarter accessor that infers scope and supports+=/-=operators
Example
-- Set options with correct scope
vim.wo.number = true -- enable line numbers for this window
vim.wo.signcolumn = 'yes' -- always show sign column in this window
vim.bo.tabstop = 2 -- 2-space tabs for this buffer
vim.bo.shiftwidth = 2
vim.bo.expandtab = true -- use spaces, not tabs
vim.o.hidden = true -- allow switching buffers without saving
Tips
vim.optis often preferred in init.lua since it handles scope automatically and supports+=,-=,^=like Vimscriptset option+=value- Use
vim.woandvim.boinFileTypeautocmds orLspAttachcallbacks to scope settings tightly - Setting a buffer-local option via
vim.wowill silently do nothing; always match the option to its correct namespace - Run
:h options.txtand look forlocal to windoworlocal to buffertags to identify the correct scope