From a8b98166cf401e2a344bb1cbda352a7e1fb333df Mon Sep 17 00:00:00 2001 From: The_miro Date: Thu, 23 Jul 2026 11:31:59 +0200 Subject: [PATCH] feat(nvim): auto-quit when only NERDTree/dadbod/Claude Code remain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After closing the file you were working on, if every remaining window in the (only) tab is NERDTree, the dadbod-ui browser, or the Claude Code terminal, there's nothing left to edit — a WinClosed autocmd force-quits (qa!) rather than leaving you staring at bare utility sidebars. qa! also bypasses the "terminal job still running" prompt for the live Claude Code process; nothing there is a real file buffer. Verified live: closing a file while another real file window remains does not quit; closing the last real file with only utility windows left (individually tested with NERDTree, dadbod-ui, and a claude-named terminal buffer) does. Co-Authored-By: Claude Sonnet 5 --- docs/md/editors.md | 6 ++++++ nvim/init.lua | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/docs/md/editors.md b/docs/md/editors.md index 1c833d1..c112162 100644 --- a/docs/md/editors.md +++ b/docs/md/editors.md @@ -97,6 +97,12 @@ Claude Code can write files outside `claudecode.nvim`'s diff-review pipeline (pl Unmodified buffers reload silently; buffers with unsaved local edits still get Vim's normal "changed outside Vim" (`W11`) prompt instead of being clobbered. +### Auto-Quit When Only Utility Windows Remain + +A `WinClosed` autocmd checks, after every window close, whether every window left in the (only) tab is one of NERDTree, the dadbod-ui browser, or the Claude Code terminal. If so — nothing left to edit — it runs `:qa!` outright, including skipping the "terminal job still running" confirmation that would otherwise block quitting while Claude Code's process is alive. + +Scoped to just those three; a real file window anywhere in the tab (or a second tab) always blocks the auto-quit. + ### Keybindings All custom bindings live in `nvim/init.lua`. Leader is `` (`vim.g.mapleader = " "`) — Space otherwise duplicates `l` (move right) in normal mode, so it was free to claim. diff --git a/nvim/init.lua b/nvim/init.lua index 89bc39a..16932bb 100644 --- a/nvim/init.lua +++ b/nvim/init.lua @@ -191,6 +191,39 @@ vim.api.nvim_create_autocmd("User", { command = "checktime", }) +-- quit outright once only plugin/utility windows remain ───────────────────── +-- After closing the file you were working on, if NERDTree, the dadbod-ui +-- browser, and/or the Claude Code terminal are the only windows left in the +-- (only) tab, there's nothing left to edit. qa! also skips the "terminal job +-- still running" confirmation for the Claude Code process; nothing here is a +-- real file buffer, so there's nothing to lose. +local function _is_utility_win(win) + local buf = vim.api.nvim_win_get_buf(win) + local ft = vim.bo[buf].filetype + if ft == "nerdtree" or ft == "dbui" then + return true + end + if vim.bo[buf].buftype == "terminal" then + return vim.api.nvim_buf_get_name(buf):match("claude") ~= nil + end + return false +end + +vim.api.nvim_create_autocmd("WinClosed", { + callback = function() + -- defer: the closed window is still mid-teardown when WinClosed fires + vim.schedule(function() + if vim.fn.tabpagenr("$") > 1 then return end + local wins = vim.api.nvim_tabpage_list_wins(0) + if #wins == 0 then return end + for _, w in ipairs(wins) do + if not _is_utility_win(w) then return end + end + vim.cmd("qa!") + end) + end, +}) + -- calendar.vim steals for month nav; restore window movement -- The plugin sets buffer-local mappings on FileType calendar, so we override -- them with { buffer = true } mappings of our own that fire after the plugin's.