Skip to content

fix: add terminal window validation and configurable persistence #60

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ For deep technical details, see [ARCHITECTURE.md](./ARCHITECTURE.md).
split_side = "right", -- "left" or "right"
split_width_percentage = 0.30,
provider = "auto", -- "auto", "snacks", or "native"
preserve_on_close = false, -- Preserve terminal process when window is closed (native provider only)
auto_close = true,
},

Expand Down
4 changes: 4 additions & 0 deletions lua/claudecode/terminal.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ local config = {
split_width_percentage = 0.30,
provider = "auto",
show_native_term_exit_tip = true,
preserve_on_close = false, -- When true, preserves terminal process when window is closed
terminal_cmd = nil,
auto_close = true,
}
Expand Down Expand Up @@ -179,6 +180,7 @@ end
-- @field user_term_config.split_width_percentage number Percentage of screen width (0.0 to 1.0, default: 0.30).
-- @field user_term_config.provider string 'snacks' or 'native' (default: 'snacks').
-- @field user_term_config.show_native_term_exit_tip boolean Show tip for exiting native terminal (default: true).
-- @field user_term_config.preserve_on_close boolean Preserve terminal process when window is closed (default: false).
-- @param p_terminal_cmd string|nil The command to run in the terminal (from main config).
function M.setup(user_term_config, p_terminal_cmd)
if user_term_config == nil then -- Allow nil, default to empty table silently
Expand Down Expand Up @@ -208,6 +210,8 @@ function M.setup(user_term_config, p_terminal_cmd)
config[k] = v
elseif k == "show_native_term_exit_tip" and type(v) == "boolean" then
config[k] = v
elseif k == "preserve_on_close" and type(v) == "boolean" then
config[k] = v
elseif k == "auto_close" and type(v) == "boolean" then
config[k] = v
else
Expand Down
10 changes: 7 additions & 3 deletions lua/claudecode/terminal/native.lua
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,9 @@ local function open_terminal(cmd_string, env_table, effective_config, focus)

winid = new_winid
bufnr = vim.api.nvim_get_current_buf()
vim.bo[bufnr].bufhidden = "wipe" -- Wipe buffer when hidden (e.g., window closed)
-- Configure buffer behavior when window is closed
local bufhidden_value = config.preserve_on_close and "hide" or "wipe"
vim.bo[bufnr].bufhidden = bufhidden_value
-- buftype=terminal is set by termopen

if focus then
Expand Down Expand Up @@ -185,8 +187,10 @@ end
local function hide_terminal()
-- Hide the terminal window but keep the buffer and job alive
if bufnr and vim.api.nvim_buf_is_valid(bufnr) and winid and vim.api.nvim_win_is_valid(winid) then
-- Set buffer to hide instead of being wiped when window closes
vim.api.nvim_buf_set_option(bufnr, "bufhidden", "hide")
-- If preserve_on_close is false (wipe mode), temporarily set to hide to preserve process
if not config.preserve_on_close then
vim.api.nvim_buf_set_option(bufnr, "bufhidden", "hide")
end

-- Close the window - this preserves the buffer and job
vim.api.nvim_win_close(winid, false)
Expand Down
19 changes: 13 additions & 6 deletions lua/claudecode/terminal/snacks.lua
Original file line number Diff line number Diff line change
Expand Up @@ -210,13 +210,20 @@ function M.focus_toggle(cmd_string, env_table, config)
-- you're NOT in it
else
logger.debug("terminal", "Focus toggle: focusing terminal")
vim.api.nvim_set_current_win(claude_term_neovim_win_id)
if terminal.buf and vim.api.nvim_buf_is_valid(terminal.buf) then
if vim.api.nvim_buf_get_option(terminal.buf, "buftype") == "terminal" then
vim.api.nvim_win_call(claude_term_neovim_win_id, function()
vim.cmd("startinsert")
end)
-- Check if window is still valid before trying to focus it
if vim.api.nvim_win_is_valid(claude_term_neovim_win_id) then
vim.api.nvim_set_current_win(claude_term_neovim_win_id)
if terminal.buf and vim.api.nvim_buf_is_valid(terminal.buf) then
if vim.api.nvim_buf_get_option(terminal.buf, "buftype") == "terminal" then
vim.api.nvim_win_call(claude_term_neovim_win_id, function()
vim.cmd("startinsert")
end)
end
end
else
-- Window was closed, reopen the terminal
logger.debug("terminal", "Focus toggle: window was closed, reopening terminal")
terminal:toggle()
end
end
-- No terminal exists
Expand Down