Skip to content

Commit 030fa7c

Browse files
authored
fix: address terminal focus error when buffer is hidden (#43)
1 parent 55aba11 commit 030fa7c

18 files changed

+836
-248
lines changed

README.md

Lines changed: 186 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ Using [lazy.nvim](https://github.com/folke/lazy.nvim):
5959
"<leader>as",
6060
"<cmd>ClaudeCodeTreeAdd<cr>",
6161
desc = "Add file",
62-
ft = { "NvimTree", "neo-tree" },
62+
ft = { "NvimTree", "neo-tree", "oil" },
6363
},
6464
},
6565
}
@@ -214,77 +214,225 @@ For deep technical details, see [ARCHITECTURE.md](./ARCHITECTURE.md).
214214

215215
See [DEVELOPMENT.md](./DEVELOPMENT.md) for build instructions and development guidelines. Tests can be run with `make test`.
216216

217-
## Advanced Setup
217+
## Configuration
218+
219+
### Quick Setup
220+
221+
For most users, the default configuration is sufficient:
222+
223+
```lua
224+
{
225+
"coder/claudecode.nvim",
226+
dependencies = {
227+
"folke/snacks.nvim", -- optional
228+
},
229+
config = true,
230+
keys = {
231+
{ "<leader>a", nil, desc = "AI/Claude Code" },
232+
{ "<leader>ac", "<cmd>ClaudeCode<cr>", desc = "Toggle Claude" },
233+
{ "<leader>af", "<cmd>ClaudeCodeFocus<cr>", desc = "Focus Claude" },
234+
{ "<leader>ar", "<cmd>ClaudeCode --resume<cr>", desc = "Resume Claude" },
235+
{ "<leader>aC", "<cmd>ClaudeCode --continue<cr>", desc = "Continue Claude" },
236+
{ "<leader>as", "<cmd>ClaudeCodeSend<cr>", mode = "v", desc = "Send to Claude" },
237+
{
238+
"<leader>as",
239+
"<cmd>ClaudeCodeTreeAdd<cr>",
240+
desc = "Add file",
241+
ft = { "NvimTree", "neo-tree", "oil" },
242+
},
243+
},
244+
}
245+
```
246+
247+
### Advanced Configuration
218248

219249
<details>
220-
<summary>Full configuration with all options</summary>
250+
<summary>Complete configuration options</summary>
221251

222252
```lua
223253
{
224254
"coder/claudecode.nvim",
225255
dependencies = {
226256
"folke/snacks.nvim", -- Optional for enhanced terminal
227257
},
258+
keys = {
259+
{ "<leader>a", nil, desc = "AI/Claude Code" },
260+
{ "<leader>ac", "<cmd>ClaudeCode<cr>", desc = "Toggle Claude" },
261+
{ "<leader>af", "<cmd>ClaudeCodeFocus<cr>", desc = "Focus Claude" },
262+
{ "<leader>ar", "<cmd>ClaudeCode --resume<cr>", desc = "Resume Claude" },
263+
{ "<leader>aC", "<cmd>ClaudeCode --continue<cr>", desc = "Continue Claude" },
264+
{ "<leader>as", "<cmd>ClaudeCodeSend<cr>", mode = "v", desc = "Send to Claude" },
265+
{
266+
"<leader>as",
267+
"<cmd>ClaudeCodeTreeAdd<cr>",
268+
desc = "Add file",
269+
ft = { "NvimTree", "neo-tree", "oil" },
270+
},
271+
},
228272
opts = {
229-
-- Server options
230-
port_range = { min = 10000, max = 65535 },
231-
auto_start = true,
232-
log_level = "info",
233-
234-
-- Terminal options
273+
-- Server Configuration
274+
port_range = { min = 10000, max = 65535 }, -- WebSocket server port range
275+
auto_start = true, -- Auto-start server on Neovim startup
276+
log_level = "info", -- "trace", "debug", "info", "warn", "error"
277+
terminal_cmd = nil, -- Custom terminal command (default: "claude")
278+
279+
-- Selection Tracking
280+
track_selection = true, -- Enable real-time selection tracking
281+
visual_demotion_delay_ms = 50, -- Delay before demoting visual selection (ms)
282+
283+
-- Connection Management
284+
connection_wait_delay = 200, -- Wait time after connection before sending queued @ mentions (ms)
285+
connection_timeout = 10000, -- Max time to wait for Claude Code connection (ms)
286+
queue_timeout = 5000, -- Max time to keep @ mentions in queue (ms)
287+
288+
-- Terminal Configuration
235289
terminal = {
236-
split_side = "right",
237-
split_width_percentage = 0.3,
238-
provider = "auto", -- "auto" (default), "snacks", or "native"
239-
auto_close = true, -- Auto-close terminal after command completion
290+
split_side = "right", -- "left" or "right"
291+
split_width_percentage = 0.30, -- Width as percentage (0.0 to 1.0)
292+
provider = "auto", -- "auto", "snacks", or "native"
293+
show_native_term_exit_tip = true, -- Show exit tip for native terminal
294+
auto_close = true, -- Auto-close terminal after command completion
240295
},
241296

242-
-- Diff options
297+
-- Diff Integration
243298
diff_opts = {
244-
auto_close_on_accept = true,
245-
vertical_split = true,
299+
auto_close_on_accept = true, -- Close diff view after accepting changes
300+
show_diff_stats = true, -- Show diff statistics
301+
vertical_split = true, -- Use vertical split for diffs
302+
open_in_current_tab = true, -- Open diffs in current tab vs new tab
246303
},
247304
},
248-
config = true,
305+
}
306+
```
307+
308+
</details>
309+
310+
### Configuration Options Explained
311+
312+
#### Server Options
313+
314+
- **`port_range`**: Port range for the WebSocket server that Claude connects to
315+
- **`auto_start`**: Whether to automatically start the integration when Neovim starts
316+
- **`terminal_cmd`**: Override the default "claude" command (useful for custom Claude installations)
317+
- **`log_level`**: Controls verbosity of plugin logs
318+
319+
#### Selection Tracking
320+
321+
- **`track_selection`**: Enables real-time selection updates sent to Claude
322+
- **`visual_demotion_delay_ms`**: Time to wait before switching from visual selection to cursor position tracking
323+
324+
#### Connection Management
325+
326+
- **`connection_wait_delay`**: Prevents overwhelming Claude with rapid @ mentions after connection
327+
- **`connection_timeout`**: How long to wait for Claude to connect before giving up
328+
- **`queue_timeout`**: How long to keep queued @ mentions before discarding them
329+
330+
#### Terminal Configuration
331+
332+
- **`split_side`**: Which side to open the terminal split (`"left"` or `"right"`)
333+
- **`split_width_percentage`**: Terminal width as a fraction of screen width (0.1 = 10%, 0.5 = 50%)
334+
- **`provider`**: Terminal implementation to use:
335+
- `"auto"`: Try snacks.nvim, fallback to native
336+
- `"snacks"`: Force snacks.nvim (requires folke/snacks.nvim)
337+
- `"native"`: Use built-in Neovim terminal
338+
- **`show_native_term_exit_tip`**: Show help text for exiting native terminal
339+
- **`auto_close`**: Automatically close terminal when commands finish
340+
341+
#### Diff Options
342+
343+
- **`auto_close_on_accept`**: Close diff view after accepting changes with `:w` or `<leader>da`
344+
- **`show_diff_stats`**: Display diff statistics (lines added/removed)
345+
- **`vertical_split`**: Use vertical split layout for diffs
346+
- **`open_in_current_tab`**: Open diffs in current tab instead of creating new tabs
347+
348+
### Example Configurations
349+
350+
#### Minimal Configuration
351+
352+
```lua
353+
{
354+
"coder/claudecode.nvim",
249355
keys = {
250356
{ "<leader>a", nil, desc = "AI/Claude Code" },
251357
{ "<leader>ac", "<cmd>ClaudeCode<cr>", desc = "Toggle Claude" },
252358
{ "<leader>af", "<cmd>ClaudeCodeFocus<cr>", desc = "Focus Claude" },
359+
{ "<leader>ar", "<cmd>ClaudeCode --resume<cr>", desc = "Resume Claude" },
360+
{ "<leader>aC", "<cmd>ClaudeCode --continue<cr>", desc = "Continue Claude" },
253361
{ "<leader>as", "<cmd>ClaudeCodeSend<cr>", mode = "v", desc = "Send to Claude" },
254362
{
255363
"<leader>as",
256364
"<cmd>ClaudeCodeTreeAdd<cr>",
257365
desc = "Add file",
258-
ft = { "NvimTree", "neo-tree" },
366+
ft = { "NvimTree", "neo-tree", "oil" },
259367
},
260-
{ "<leader>ao", "<cmd>ClaudeCodeOpen<cr>", desc = "Open Claude" },
261-
{ "<leader>ax", "<cmd>ClaudeCodeClose<cr>", desc = "Close Claude" },
368+
},
369+
opts = {
370+
log_level = "warn", -- Reduce log verbosity
371+
auto_start = false, -- Manual startup only
262372
},
263373
}
264374
```
265375

266-
</details>
267-
268-
### Terminal Auto-Close Behavior
269-
270-
The `auto_close` option controls what happens when Claude commands finish:
271-
272-
**When `auto_close = true` (default):**
273-
274-
- Terminal automatically closes after command completion
275-
- Error notifications shown for failed commands (non-zero exit codes)
276-
- Clean workflow for quick command execution
376+
#### Power User Configuration
277377

278-
**When `auto_close = false`:**
378+
```lua
379+
{
380+
"coder/claudecode.nvim",
381+
keys = {
382+
{ "<leader>a", nil, desc = "AI/Claude Code" },
383+
{ "<leader>ac", "<cmd>ClaudeCode<cr>", desc = "Toggle Claude" },
384+
{ "<leader>af", "<cmd>ClaudeCodeFocus<cr>", desc = "Focus Claude" },
385+
{ "<leader>ar", "<cmd>ClaudeCode --resume<cr>", desc = "Resume Claude" },
386+
{ "<leader>aC", "<cmd>ClaudeCode --continue<cr>", desc = "Continue Claude" },
387+
{ "<leader>as", "<cmd>ClaudeCodeSend<cr>", mode = "v", desc = "Send to Claude" },
388+
{
389+
"<leader>as",
390+
"<cmd>ClaudeCodeTreeAdd<cr>",
391+
desc = "Add file",
392+
ft = { "NvimTree", "neo-tree", "oil" },
393+
},
394+
},
395+
opts = {
396+
log_level = "debug",
397+
visual_demotion_delay_ms = 100, -- Slower selection demotion
398+
connection_wait_delay = 500, -- Longer delay for @ mention batching
399+
terminal = {
400+
split_side = "left",
401+
split_width_percentage = 0.4, -- Wider terminal
402+
provider = "snacks",
403+
auto_close = false, -- Keep terminal open to review output
404+
},
405+
diff_opts = {
406+
vertical_split = false, -- Horizontal diffs
407+
open_in_current_tab = false, -- New tabs for diffs
408+
},
409+
},
410+
}
411+
```
279412

280-
- Terminal stays open after command completion
281-
- Allows reviewing command output and any error messages
282-
- Useful for debugging or when you want to see detailed output
413+
#### Custom Claude Installation
283414

284415
```lua
285-
terminal = {
286-
provider = "snacks",
287-
auto_close = false, -- Keep terminal open to review output
416+
{
417+
"coder/claudecode.nvim",
418+
keys = {
419+
{ "<leader>a", nil, desc = "AI/Claude Code" },
420+
{ "<leader>ac", "<cmd>ClaudeCode<cr>", desc = "Toggle Claude" },
421+
{ "<leader>af", "<cmd>ClaudeCodeFocus<cr>", desc = "Focus Claude" },
422+
{ "<leader>ar", "<cmd>ClaudeCode --resume<cr>", desc = "Resume Claude" },
423+
{ "<leader>aC", "<cmd>ClaudeCode --continue<cr>", desc = "Continue Claude" },
424+
{ "<leader>as", "<cmd>ClaudeCodeSend<cr>", mode = "v", desc = "Send to Claude" },
425+
{
426+
"<leader>as",
427+
"<cmd>ClaudeCodeTreeAdd<cr>",
428+
desc = "Add file",
429+
ft = { "NvimTree", "neo-tree", "oil" },
430+
},
431+
},
432+
opts = {
433+
terminal_cmd = "/opt/claude/bin/claude", -- Custom Claude path
434+
port_range = { min = 20000, max = 25000 }, -- Different port range
435+
},
288436
}
289437
```
290438

STORY.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
While browsing Reddit at DevOpsCon in London, I stumbled upon a post that caught my eye: someone mentioned finding .vsix files in Anthropic's npm package for their Claude Code VS Code extension.
66

7-
Link to the Reddit post: https://www.reddit.com/r/ClaudeAI/comments/1klpzvl/hidden_jetbrains_vs_code_plugin_in_todays_release/
7+
Link to the Reddit post: <https://www.reddit.com/r/ClaudeAI/comments/1klpzvl/hidden_jetbrains_vs_code_plugin_in_todays_release/>
88

99
My first thought? "No way, they wouldn't ship the source like that."
1010

@@ -45,7 +45,7 @@ What I discovered was fascinating:
4545

4646
Armed with this knowledge, I faced a new challenge: I wanted this in Neovim, but I didn't know Lua.
4747

48-
So I did what any reasonable person would do in 2024 — I used AI to help me build it. Using Roo Code with Gemini 2.5 Pro, I scaffolded a Neovim plugin that implements the same protocol.
48+
So I did what any reasonable person would do in 2025 — I used AI to help me build it. Using Roo Code with Gemini 2.5 Pro, I scaffolded a Neovim plugin that implements the same protocol. (Note: Claude 4 models were not publicly available at the time of writing the extension.)
4949

5050
The irony isn't lost on me: I used AI to reverse-engineer an AI tool, then used AI to build a plugin for AI.
5151

dev-config.lua

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
-- Development configuration for claudecode.nvim
22
-- This is Thomas's personal config for developing claudecode.nvim
33
-- Symlink this to your personal Neovim config:
4-
-- ln -s ~/GitHub/claudecode.nvim/dev-config.lua ~/.config/nvim/lua/plugins/dev-claudecode.lua
4+
-- ln -s ~/projects/claudecode.nvim/dev-config.lua ~/.config/nvim/lua/plugins/dev-claudecode.lua
55

66
return {
77
"coder/claudecode.nvim",
88
dev = true, -- Use local development version
9-
dir = "~/GitHub/claudecode.nvim", -- Adjust path as needed
109
keys = {
1110
-- AI/Claude Code prefix
1211
{ "<leader>a", nil, desc = "AI/Claude Code" },
@@ -23,7 +22,7 @@ return {
2322
"<leader>as",
2423
"<cmd>ClaudeCodeTreeAdd<cr>",
2524
desc = "Add file from tree",
26-
ft = { "NvimTree", "neo-tree" },
25+
ft = { "NvimTree", "neo-tree", "oil" },
2726
},
2827

2928
-- Development helpers
@@ -34,11 +33,42 @@ return {
3433
{ "<leader>aQ", "<cmd>ClaudeCodeStop<cr>", desc = "Stop Claude Server" },
3534
},
3635

37-
-- Development configuration
36+
-- Development configuration - all options shown with defaults commented out
3837
opts = {
39-
-- auto_start = true,
38+
-- Server Configuration
39+
-- port_range = { min = 10000, max = 65535 }, -- WebSocket server port range
40+
-- auto_start = true, -- Auto-start server on Neovim startup
41+
-- log_level = "info", -- "trace", "debug", "info", "warn", "error"
42+
-- terminal_cmd = nil, -- Custom terminal command (default: "claude")
43+
44+
-- Selection Tracking
45+
-- track_selection = true, -- Enable real-time selection tracking
46+
-- visual_demotion_delay_ms = 50, -- Delay before demoting visual selection (ms)
47+
48+
-- Connection Management
49+
-- connection_wait_delay = 200, -- Wait time after connection before sending queued @ mentions (ms)
50+
-- connection_timeout = 10000, -- Max time to wait for Claude Code connection (ms)
51+
-- queue_timeout = 5000, -- Max time to keep @ mentions in queue (ms)
52+
53+
-- Diff Integration
54+
-- diff_opts = {
55+
-- auto_close_on_accept = true, -- Close diff view after accepting changes
56+
-- show_diff_stats = true, -- Show diff statistics
57+
-- vertical_split = true, -- Use vertical split for diffs
58+
-- open_in_current_tab = true, -- Open diffs in current tab vs new tab
59+
-- },
60+
61+
-- Terminal Configuration
62+
-- terminal = {
63+
-- split_side = "right", -- "left" or "right"
64+
-- split_width_percentage = 0.30, -- Width as percentage (0.0 to 1.0)
65+
-- provider = "auto", -- "auto", "snacks", or "native"
66+
-- show_native_term_exit_tip = true, -- Show exit tip for native terminal
67+
-- auto_close = true, -- Auto-close terminal after command completion
68+
-- },
69+
70+
-- Development overrides (uncomment as needed)
4071
-- log_level = "debug",
41-
-- terminal_cmd = "claude --debug",
4272
-- terminal = {
4373
-- provider = "native",
4474
-- auto_close = false, -- Keep terminals open to see output

lua/claudecode/config.lua

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ M.defaults = {
99
log_level = "info",
1010
track_selection = true,
1111
visual_demotion_delay_ms = 50, -- Milliseconds to wait before demoting a visual selection
12+
connection_wait_delay = 200, -- Milliseconds to wait after connection before sending queued @ mentions
13+
connection_timeout = 10000, -- Maximum time to wait for Claude Code to connect (milliseconds)
14+
queue_timeout = 5000, -- Maximum time to keep @ mentions in queue (milliseconds)
1215
diff_opts = {
1316
auto_close_on_accept = true,
1417
show_diff_stats = true,
@@ -53,6 +56,18 @@ function M.validate(config)
5356
"visual_demotion_delay_ms must be a non-negative number"
5457
)
5558

59+
assert(
60+
type(config.connection_wait_delay) == "number" and config.connection_wait_delay >= 0,
61+
"connection_wait_delay must be a non-negative number"
62+
)
63+
64+
assert(
65+
type(config.connection_timeout) == "number" and config.connection_timeout > 0,
66+
"connection_timeout must be a positive number"
67+
)
68+
69+
assert(type(config.queue_timeout) == "number" and config.queue_timeout > 0, "queue_timeout must be a positive number")
70+
5671
assert(type(config.diff_opts) == "table", "diff_opts must be a table")
5772
assert(type(config.diff_opts.auto_close_on_accept) == "boolean", "diff_opts.auto_close_on_accept must be a boolean")
5873
assert(type(config.diff_opts.show_diff_stats) == "boolean", "diff_opts.show_diff_stats must be a boolean")

0 commit comments

Comments
 (0)