Skip to content

[idea] Auto-lcd to git root on file open #165

Description

@stanfish06

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions