Skip to content
Merged
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
4 changes: 4 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,13 +289,17 @@ require("claudecode").setup({
The `diff_opts` configuration allows you to customize diff behavior:

- `keep_terminal_focus` (boolean, default: `false`) - When enabled, keeps focus in the Claude Code terminal when a diff opens instead of moving focus to the diff buffer. This allows you to continue using terminal keybindings like `<CR>` for accepting/rejecting diffs without accidentally triggering other mappings.
- `open_in_new_tab` (boolean, default: `false`) - Open diffs in a new tab instead of the current tab.
- `hide_terminal_in_new_tab` (boolean, default: `false`) - When opening diffs in a new tab, do not show the Claude terminal split in that new tab. The terminal remains in the original tab, giving maximum screen estate for reviewing the diff.

**Example use case**: If you frequently use `<CR>` or arrow keys in the Claude Code terminal to accept/reject diffs, enable this option to prevent focus from moving to the diff buffer where `<CR>` might trigger unintended actions.

```lua
require("claudecode").setup({
diff_opts = {
keep_terminal_focus = true, -- If true, moves focus back to terminal after diff opens
open_in_new_tab = true, -- Open diff in a separate tab
hide_terminal_in_new_tab = true, -- In the new tab, do not show Claude terminal
auto_close_on_accept = true,
show_diff_stats = true,
vertical_split = true,
Expand Down
28 changes: 14 additions & 14 deletions dev-config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -40,29 +40,29 @@ return {
},

-- Development configuration - all options shown with defaults commented out
---@type ClaudeCodeConfig
opts = {
-- Server Configuration
-- port_range = { min = 10000, max = 65535 }, -- WebSocket server port range
-- auto_start = true, -- Auto-start server on Neovim startup
-- log_level = "info", -- "trace", "debug", "info", "warn", "error"
-- terminal_cmd = nil, -- Custom terminal command (default: "claude")
-- port_range = { min = 10000, max = 65535 }, -- WebSocket server port range
-- auto_start = true, -- Auto-start server on Neovim startup
-- log_level = "info", -- "trace", "debug", "info", "warn", "error"
-- terminal_cmd = nil, -- Custom terminal command (default: "claude")

-- Selection Tracking
-- track_selection = true, -- Enable real-time selection tracking
-- visual_demotion_delay_ms = 50, -- Delay before demoting visual selection (ms)
-- track_selection = true, -- Enable real-time selection tracking
-- visual_demotion_delay_ms = 50, -- Delay before demoting visual selection (ms)

-- Connection Management
-- connection_wait_delay = 200, -- Wait time after connection before sending queued @ mentions (ms)
-- connection_timeout = 10000, -- Max time to wait for Claude Code connection (ms)
-- queue_timeout = 5000, -- Max time to keep @ mentions in queue (ms)
-- connection_wait_delay = 200, -- Wait time after connection before sending queued @ mentions (ms)
-- connection_timeout = 10000, -- Max time to wait for Claude Code connection (ms)
-- queue_timeout = 5000, -- Max time to keep @ mentions in queue (ms)

-- Diff Integration
-- diff_opts = {
-- auto_close_on_accept = true, -- Close diff view after accepting changes
-- show_diff_stats = true, -- Show diff statistics
-- vertical_split = true, -- Use vertical split for diffs
-- open_in_current_tab = true, -- Open diffs in current tab vs new tab
-- keep_terminal_focus = false, -- If true, moves focus back to terminal after diff opens
-- layout = "horizontal", -- "vertical" or "horizontal" diff layout
-- open_in_new_tab = true, -- Open diff in a new tab (false = use current tab)
-- keep_terminal_focus = true, -- Keep focus in terminal after opening diff
-- hide_terminal_in_new_tab = true, -- Hide Claude terminal in the new diff tab for more review space
-- },

-- Terminal Configuration
Expand Down
2 changes: 1 addition & 1 deletion fixtures/nvim-tree/lazy-lock.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"lazy.nvim": { "branch": "main", "commit": "6c3bda4aca61a13a9c63f1c1d1b16b9d3be90d7a" },
"nvim-tree.lua": { "branch": "master", "commit": "0a7fcdf3f8ba208f4260988a198c77ec11748339" },
"nvim-tree.lua": { "branch": "master", "commit": "0a52012d611f3c1492b8d2aba363fabf734de91d" },
"nvim-web-devicons": { "branch": "master", "commit": "3362099de3368aa620a8105b19ed04c2053e38c0" },
"tokyonight.nvim": { "branch": "main", "commit": "057ef5d260c1931f1dffd0f052c685dcd14100a3" }
}
54 changes: 46 additions & 8 deletions lua/claudecode/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@ M.defaults = {
connection_timeout = 10000, -- Maximum time to wait for Claude Code to connect (milliseconds)
queue_timeout = 5000, -- Maximum time to keep @ mentions in queue (milliseconds)
diff_opts = {
auto_close_on_accept = true,
show_diff_stats = true,
vertical_split = true,
open_in_current_tab = true, -- Use current tab instead of creating new tab
layout = "vertical",
open_in_new_tab = false, -- Open diff in a new tab (false = use current tab)
keep_terminal_focus = false, -- If true, moves focus back to terminal after diff opens
hide_terminal_in_new_tab = false, -- If true and opening in a new tab, do not show Claude terminal there
},
models = {
{ name = "Claude Opus 4.1 (Latest)", value = "opus" },
Expand Down Expand Up @@ -106,13 +105,39 @@ function M.validate(config)
assert(type(config.queue_timeout) == "number" and config.queue_timeout > 0, "queue_timeout must be a positive number")

assert(type(config.diff_opts) == "table", "diff_opts must be a table")
assert(type(config.diff_opts.auto_close_on_accept) == "boolean", "diff_opts.auto_close_on_accept must be a boolean")
assert(type(config.diff_opts.show_diff_stats) == "boolean", "diff_opts.show_diff_stats must be a boolean")
assert(type(config.diff_opts.vertical_split) == "boolean", "diff_opts.vertical_split must be a boolean")
assert(type(config.diff_opts.open_in_current_tab) == "boolean", "diff_opts.open_in_current_tab must be a boolean")
-- New diff options (optional validation to allow backward compatibility)
if config.diff_opts.layout ~= nil then
assert(
config.diff_opts.layout == "vertical" or config.diff_opts.layout == "horizontal",
"diff_opts.layout must be 'vertical' or 'horizontal'"
)
end
if config.diff_opts.open_in_new_tab ~= nil then
assert(type(config.diff_opts.open_in_new_tab) == "boolean", "diff_opts.open_in_new_tab must be a boolean")
end
if config.diff_opts.keep_terminal_focus ~= nil then
assert(type(config.diff_opts.keep_terminal_focus) == "boolean", "diff_opts.keep_terminal_focus must be a boolean")
end
if config.diff_opts.hide_terminal_in_new_tab ~= nil then
assert(
type(config.diff_opts.hide_terminal_in_new_tab) == "boolean",
"diff_opts.hide_terminal_in_new_tab must be a boolean"
)
end

-- Legacy diff options (accept if present to avoid breaking old configs)
if config.diff_opts.auto_close_on_accept ~= nil then
assert(type(config.diff_opts.auto_close_on_accept) == "boolean", "diff_opts.auto_close_on_accept must be a boolean")
end
if config.diff_opts.show_diff_stats ~= nil then
assert(type(config.diff_opts.show_diff_stats) == "boolean", "diff_opts.show_diff_stats must be a boolean")
end
if config.diff_opts.vertical_split ~= nil then
assert(type(config.diff_opts.vertical_split) == "boolean", "diff_opts.vertical_split must be a boolean")
end
if config.diff_opts.open_in_current_tab ~= nil then
assert(type(config.diff_opts.open_in_current_tab) == "boolean", "diff_opts.open_in_current_tab must be a boolean")
end

-- Validate env
assert(type(config.env) == "table", "env must be a table")
Expand Down Expand Up @@ -160,6 +185,19 @@ function M.apply(user_config)
end
end

-- Backward compatibility: map legacy diff options to new fields if provided
if config.diff_opts then
local d = config.diff_opts
-- Map vertical_split -> layout (only if layout not explicitly set)
if d.layout == nil and type(d.vertical_split) == "boolean" then
d.layout = d.vertical_split and "vertical" or "horizontal"
end
-- Map open_in_current_tab -> open_in_new_tab (invert; only if not explicitly set)
if d.open_in_new_tab == nil and type(d.open_in_current_tab) == "boolean" then
d.open_in_new_tab = not d.open_in_current_tab
end
end

M.validate(config)

return config
Expand Down
Loading