diff --git a/lua/claudecode/config.lua b/lua/claudecode/config.lua index 83ff74a..6b0bad7 100644 --- a/lua/claudecode/config.lua +++ b/lua/claudecode/config.lua @@ -6,6 +6,7 @@ M.defaults = { port_range = { min = 10000, max = 65535 }, auto_start = true, terminal_cmd = nil, + env = {}, -- Custom environment variables for Claude terminal log_level = "info", track_selection = true, visual_demotion_delay_ms = 50, -- Milliseconds to wait before demoting a visual selection @@ -61,6 +62,13 @@ function M.validate(config) 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") + -- Validate env + assert(type(config.env) == "table", "env must be a table") + for key, value in pairs(config.env) do + assert(type(key) == "string", "env keys must be strings") + assert(type(value) == "string", "env values must be strings") + end + return true end diff --git a/lua/claudecode/init.lua b/lua/claudecode/init.lua index 489785c..b94ac7c 100644 --- a/lua/claudecode/init.lua +++ b/lua/claudecode/init.lua @@ -34,6 +34,7 @@ M.version = { --- @field port_range {min: integer, max: integer} Port range for WebSocket server. --- @field auto_start boolean Auto-start WebSocket server on Neovim startup. --- @field terminal_cmd string|nil Custom terminal command to use when launching Claude. +--- @field env table Custom environment variables for Claude terminal. --- @field log_level "trace"|"debug"|"info"|"warn"|"error" Log level. --- @field track_selection boolean Enable sending selection updates to Claude. --- @field visual_demotion_delay_ms number Milliseconds to wait before demoting a visual selection. @@ -44,6 +45,7 @@ local default_config = { port_range = { min = 10000, max = 65535 }, auto_start = true, terminal_cmd = nil, + env = {}, log_level = "info", track_selection = true, visual_demotion_delay_ms = 200, @@ -97,14 +99,14 @@ function M.setup(opts) local logger = require("claudecode.logger") logger.setup(M.state.config) - -- Setup terminal module: always try to call setup to pass terminal_cmd, + -- Setup terminal module: always try to call setup to pass terminal_cmd and env, -- 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 -- terminal_opts might be nil if user only configured top-level terminal_cmd -- and not specific terminal appearance options. -- The terminal.setup function handles nil for its first argument. - terminal_module.setup(terminal_opts, M.state.config.terminal_cmd) + terminal_module.setup(terminal_opts, M.state.config.terminal_cmd, M.state.config.env) else logger.error("init", "Failed to load claudecode.terminal module for setup.") end diff --git a/lua/claudecode/terminal.lua b/lua/claudecode/terminal.lua index 4880388..4e51deb 100644 --- a/lua/claudecode/terminal.lua +++ b/lua/claudecode/terminal.lua @@ -22,6 +22,7 @@ local term_module_config = { provider = "snacks", show_native_term_exit_tip = true, terminal_cmd = nil, -- Will be set by setup() from main config + env = {}, -- Will be set by setup() from main config } --- State to keep track of the managed Claude terminal instance (from Snacks). @@ -53,7 +54,8 @@ end -- @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). -- @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) +-- @param p_env table|nil Custom environment variables to pass to the terminal (from main config). +function M.setup(user_term_config, p_terminal_cmd, p_env) if user_term_config == nil then -- Allow nil, default to empty table silently user_term_config = {} elseif type(user_term_config) ~= "table" then -- Warn if it's not nil AND not a table @@ -71,6 +73,16 @@ function M.setup(user_term_config, p_terminal_cmd) term_module_config.terminal_cmd = nil -- Fallback to default behavior in get_claude_command end + if p_env == nil or type(p_env) == "table" then + term_module_config.env = p_env or {} + else + vim.notify( + "claudecode.terminal.setup: Invalid env provided: " .. tostring(p_env) .. ". Using empty table.", + vim.log.levels.WARN + ) + term_module_config.env = {} + end + for k, v in pairs(user_term_config) do if term_module_config[k] ~= nil and k ~= "terminal_cmd" then -- terminal_cmd is handled above if k == "split_side" and (v == "left" or v == "right") then @@ -351,6 +363,11 @@ local function get_claude_command_and_env() env_table["CLAUDE_CODE_SSE_PORT"] = tostring(sse_port_value) end + -- Merge custom environment variables from config + for key, value in pairs(term_module_config.env) do + env_table[key] = value + end + return cmd_string, env_table end