What
Add a BufEnter autocmd that calls lcd (local working directory change) to the git root of the file being opened. This makes the current window's working directory track the project root automatically.
Where
lua/config/options.lua — near the existing vim.g.netrw_keepdir = 0 setting (line 74) and the lcd tip in init.lua (line 38: "lcd allows you to set root directory for current window").
Why it matters
The config explicitly documents lcd as useful ("lcd allows you to set root directory for current window") but requires manual invocation. Several parts of the config depend on the working directory matching the project root:
fzf.files and fzf.live_grep search from cwd — if cwd is not the project root, file/grep pickers miss files or show wrong relative paths
- The statusline's
current_file() (statusline.lua:256–273) shows the path relative to getcwd(0, 0) — a wrong cwd gives confusing path display
vim.fn.finddir(".git", ".;") and LSP root detection both walk up from the file, but fzf and Compile both use cwd directly
makeprg = "" + :Compile runs from cwd — running it with cwd in a subdirectory means Makefile targets miss files at the root
An automatic lcd on BufEnter closes this gap for the normal file-open workflow without affecting buffers that don't belong to a git project.
Suggested implementation
-- lua/config/options.lua, near the netrw_keepdir setting
vim.api.nvim_create_autocmd("BufEnter", {
callback = function()
-- only for normal file buffers with a path
local buf = vim.api.nvim_get_current_buf()
if vim.bo[buf].buftype ~= "" then return end
local path = vim.api.nvim_buf_get_name(buf)
if path == "" then return end
-- walk up the directory tree to find .git
local git_root = vim.fs.root(path, ".git")
if git_root then
vim.cmd("lcd " .. vim.fn.fnameescape(git_root))
end
end,
})
vim.fs.root() is a Neovim 0.10+ built-in that walks up from a path looking for an anchor — no shell calls or system() needed. Uses lcd (window-local) rather than cd (global) so each split/tab can independently track its own project root.
Notes
vim.fs.root() is already used implicitly by LSP root detection — this makes the editor's cwd consistent with what LSPs already compute.
- The
lcd approach (window-local) means different windows can have different project roots, which is the right behaviour for multi-project monorepo sessions.
- Potential friction: jumping to a file in a dependency or system path will
lcd to that directory's git root (e.g., /usr/share/… may not have .git, so it silently does nothing — safe). For non-git projects this is a no-op.
- If
vim.g.netrw_keepdir = 0 (already set) causes netrw to follow directories, the autocmd adds the equivalent behaviour for regular files.
What
Add a
BufEnterautocmd that callslcd(local working directory change) to the git root of the file being opened. This makes the current window's working directory track the project root automatically.Where
lua/config/options.lua— near the existingvim.g.netrw_keepdir = 0setting (line 74) and thelcdtip ininit.lua(line 38: "lcd allows you to set root directory for current window").Why it matters
The config explicitly documents
lcdas useful ("lcd allows you to set root directory for current window") but requires manual invocation. Several parts of the config depend on the working directory matching the project root:fzf.filesandfzf.live_grepsearch fromcwd— ifcwdis not the project root, file/grep pickers miss files or show wrong relative pathscurrent_file()(statusline.lua:256–273) shows the path relative togetcwd(0, 0)— a wrongcwdgives confusing path displayvim.fn.finddir(".git", ".;")and LSP root detection both walk up from the file, but fzf and Compile both usecwddirectlymakeprg = ""+:Compileruns fromcwd— running it withcwdin a subdirectory means Makefile targets miss files at the rootAn automatic
lcdonBufEntercloses this gap for the normal file-open workflow without affecting buffers that don't belong to a git project.Suggested implementation
vim.fs.root()is a Neovim 0.10+ built-in that walks up from a path looking for an anchor — no shell calls orsystem()needed. Useslcd(window-local) rather thancd(global) so each split/tab can independently track its own project root.Notes
vim.fs.root()is already used implicitly by LSP root detection — this makes the editor'scwdconsistent with what LSPs already compute.lcdapproach (window-local) means different windows can have different project roots, which is the right behaviour for multi-project monorepo sessions.lcdto that directory's git root (e.g.,/usr/share/…may not have.git, so it silently does nothing — safe). For non-git projects this is a no-op.vim.g.netrw_keepdir = 0(already set) causes netrw to follow directories, the autocmd adds the equivalent behaviour for regular files.