Skip to content

feat: add terminal_enabled config flag for the built in nvim terminal #73

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 1 commit 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
3 changes: 3 additions & 0 deletions lua/claudecode/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ M.defaults = {
port_range = { min = 10000, max = 65535 },
auto_start = true,
terminal_cmd = nil,
enable_terminal = true, -- Enable built-in terminal integration (set to false to use external terminal like tmux)
log_level = "info",
track_selection = true,
visual_demotion_delay_ms = 50, -- Milliseconds to wait before demoting a visual selection
Expand Down Expand Up @@ -51,6 +52,8 @@ function M.validate(config)

assert(type(config.track_selection) == "boolean", "track_selection must be a boolean")

assert(type(config.enable_terminal) == "boolean", "enable_terminal must be a boolean")

assert(
type(config.visual_demotion_delay_ms) == "number" and config.visual_demotion_delay_ms >= 0,
"visual_demotion_delay_ms must be a non-negative number"
Expand Down
118 changes: 62 additions & 56 deletions lua/claudecode/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ function M.send_at_mention(file_path, start_line, end_line, context)
if M.is_claude_connected() then
-- Claude is connected, send immediately and ensure terminal is visible
local success, error_msg = M._broadcast_at_mention(file_path, start_line, end_line)
if success then
if success and M.state.config.enable_terminal then
local terminal = require("claudecode.terminal")
terminal.ensure_visible()
end
Expand All @@ -276,9 +276,11 @@ function M.send_at_mention(file_path, start_line, end_line, context)

queue_at_mention(mention_data)

-- Launch terminal with Claude Code
local terminal = require("claudecode.terminal")
terminal.open()
-- Launch terminal with Claude Code if enabled
if M.state.config.enable_terminal then
local terminal = require("claudecode.terminal")
terminal.open()
end

logger.debug(context, "Queued @ mention and launched Claude Code: " .. file_path)

Expand Down Expand Up @@ -307,15 +309,17 @@ function M.setup(opts)

-- Setup terminal module: always try to call setup to pass terminal_cmd,
-- even if terminal_opts (for split_side etc.) are not provided.
local terminal_setup_ok, terminal_module = pcall(require, "claudecode.terminal")
if terminal_setup_ok then
-- Guard in case tests or user replace the module with a minimal stub without `setup`.
if type(terminal_module.setup) == "function" then
-- terminal_opts might be nil, which the setup function should handle gracefully.
terminal_module.setup(terminal_opts, M.state.config.terminal_cmd)
if M.state.config.enable_terminal then
local terminal_setup_ok, terminal_module = pcall(require, "claudecode.terminal")
if terminal_setup_ok then
-- Guard in case tests or user replace the module with a minimal stub without `setup`.
if type(terminal_module.setup) == "function" then
-- terminal_opts might be nil, which the setup function should handle gracefully.
terminal_module.setup(terminal_opts, M.state.config.terminal_cmd)
end
else
logger.error("init", "Failed to load claudecode.terminal module for setup.")
end
else
logger.error("init", "Failed to load claudecode.terminal module for setup.")
end

local diff = require("claudecode.diff")
Expand Down Expand Up @@ -882,50 +886,52 @@ function M._create_commands()
desc = "Add specified file or directory to Claude Code context with optional line range",
})

local terminal_ok, terminal = pcall(require, "claudecode.terminal")
if terminal_ok then
vim.api.nvim_create_user_command("ClaudeCode", function(opts)
local current_mode = vim.fn.mode()
if current_mode == "v" or current_mode == "V" or current_mode == "\22" then
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<Esc>", true, false, true), "n", false)
end
local cmd_args = opts.args and opts.args ~= "" and opts.args or nil
terminal.simple_toggle({}, cmd_args)
end, {
nargs = "*",
desc = "Toggle the Claude Code terminal window (simple show/hide) with optional arguments",
})

vim.api.nvim_create_user_command("ClaudeCodeFocus", function(opts)
local current_mode = vim.fn.mode()
if current_mode == "v" or current_mode == "V" or current_mode == "\22" then
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<Esc>", true, false, true), "n", false)
end
local cmd_args = opts.args and opts.args ~= "" and opts.args or nil
terminal.focus_toggle({}, cmd_args)
end, {
nargs = "*",
desc = "Smart focus/toggle Claude Code terminal (switches to terminal if not focused, hides if focused)",
})

vim.api.nvim_create_user_command("ClaudeCodeOpen", function(opts)
local cmd_args = opts.args and opts.args ~= "" and opts.args or nil
terminal.open({}, cmd_args)
end, {
nargs = "*",
desc = "Open the Claude Code terminal window with optional arguments",
})

vim.api.nvim_create_user_command("ClaudeCodeClose", function()
terminal.close()
end, {
desc = "Close the Claude Code terminal window",
})
else
logger.error(
"init",
"Terminal module not found. Terminal commands (ClaudeCode, ClaudeCodeOpen, ClaudeCodeClose) not registered."
)
if M.state.config.enable_terminal then
local terminal_ok, terminal = pcall(require, "claudecode.terminal")
if terminal_ok then
vim.api.nvim_create_user_command("ClaudeCode", function(opts)
local current_mode = vim.fn.mode()
if current_mode == "v" or current_mode == "V" or current_mode == "\22" then
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<Esc>", true, false, true), "n", false)
end
local cmd_args = opts.args and opts.args ~= "" and opts.args or nil
terminal.simple_toggle({}, cmd_args)
end, {
nargs = "*",
desc = "Toggle the Claude Code terminal window (simple show/hide) with optional arguments",
})

vim.api.nvim_create_user_command("ClaudeCodeFocus", function(opts)
local current_mode = vim.fn.mode()
if current_mode == "v" or current_mode == "V" or current_mode == "\22" then
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<Esc>", true, false, true), "n", false)
end
local cmd_args = opts.args and opts.args ~= "" and opts.args or nil
terminal.focus_toggle({}, cmd_args)
end, {
nargs = "*",
desc = "Smart focus/toggle Claude Code terminal (switches to terminal if not focused, hides if focused)",
})

vim.api.nvim_create_user_command("ClaudeCodeOpen", function(opts)
local cmd_args = opts.args and opts.args ~= "" and opts.args or nil
terminal.open({}, cmd_args)
end, {
nargs = "*",
desc = "Open the Claude Code terminal window with optional arguments",
})

vim.api.nvim_create_user_command("ClaudeCodeClose", function()
terminal.close()
end, {
desc = "Close the Claude Code terminal window",
})
else
logger.error(
"init",
"Terminal module not found. Terminal commands (ClaudeCode, ClaudeCodeOpen, ClaudeCodeClose) not registered."
)
end
end

-- Diff management commands
Expand Down
1 change: 1 addition & 0 deletions tests/config_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ describe("Config module", function()
port_range = { min = 10000, max = 65535 },
auto_start = true,
terminal_cmd = "toggleterm",
enable_terminal = true,
log_level = "debug",
track_selection = false,
visual_demotion_delay_ms = 50,
Expand Down
4 changes: 4 additions & 0 deletions tests/integration/command_args_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,13 @@ describe("ClaudeCode command arguments integration", function()
port_range = { min = 10000, max = 65535 },
auto_start = false,
terminal_cmd = nil,
enable_terminal = true,
log_level = "info",
track_selection = true,
visual_demotion_delay_ms = 50,
connection_wait_delay = 200,
connection_timeout = 10000,
queue_timeout = 5000,
diff_opts = {
auto_close_on_accept = true,
show_diff_stats = true,
Expand Down
1 change: 1 addition & 0 deletions tests/unit/config_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ describe("Configuration", function()
port_range = { min = 10000, max = 65535 },
auto_start = true,
terminal_cmd = "toggleterm",
enable_terminal = true,
log_level = "debug",
track_selection = false,
visual_demotion_delay_ms = 50,
Expand Down
Loading