Skip to content

Comments

Fix terminal cleanup when Claude process exits#106

Merged
greggh merged 1 commit intogreggh:mainfrom
shkm:fix/terminal-exit-cleanup
Feb 4, 2026
Merged

Fix terminal cleanup when Claude process exits#106
greggh merged 1 commit intogreggh:mainfrom
shkm:fix/terminal-exit-cleanup

Conversation

@shkm
Copy link
Contributor

@shkm shkm commented Feb 4, 2026

Summary

Noticed this when running with a floating window.

Fixes two issues when the Claude process exits (via ctrl-c, ctrl-d, or pressing Enter after "Process exited"):

  1. "E95: Buffer with this name already exists" error on toggle - When toggling after the process had exited, is_valid_terminal_buffer() correctly detected the dead terminal and cleared the instance reference, but the old buffer wasn't deleted. The new instance then failed when trying to use the same buffer name.

  2. Empty floating window lingers after exit - Pressing Enter after "Process exited" would close the terminal job but leave the floating window open with an empty buffer.

Changes

  • terminal.lua: In toggle(), when detecting a dead terminal buffer, close any windows showing it and delete the buffer before creating a new instance.

  • file_refresh.lua: In TermClose autocmd, clean up instance tracking, close the floating window, and delete the buffer.

Test plan

  • Open Claude with :ClaudeCode in floating window mode
  • Exit with ctrl-d until "Process exited 0" appears
  • Press ctrl+' (or toggle key) - should open a fresh Claude instance without error
  • Open Claude again, exit with ctrl-d, then press Enter - floating window should close automatically

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Improved terminal buffer cleanup on closure, ensuring proper restoration of editor settings.
    • Enhanced handling of invalid terminal buffers with more aggressive UI cleanup, closing associated windows and freeing buffer resources.
    • Better resource management for terminal sessions to prevent orphaned windows and buffers.

When the Claude process exits (via ctrl-c, ctrl-d, or pressing Enter after
"Process exited"), the plugin now properly cleans up:

1. In toggle(): When detecting a dead terminal buffer, close any windows
   showing it and delete the buffer before creating a new instance. This
   fixes "E95: Buffer with this name already exists" error.

2. In TermClose autocmd: Clean up instance tracking, close the floating
   window, and delete the buffer. This prevents an empty floating window
   from lingering after the terminal exits.
@coderabbitai
Copy link

coderabbitai bot commented Feb 4, 2026

📝 Walkthrough

Walkthrough

Enhanced terminal buffer cleanup in Claude Code by improving the TermClose autocommand callback to use proper callback signatures and implementing more aggressive cleanup that closes windows and deletes buffers when invalid states are detected.

Changes

Cohort / File(s) Summary
Terminal Buffer Cleanup
lua/claude-code/file_refresh.lua, lua/claude-code/terminal.lua
Modified TermClose autocommand callback to use callback signature with args, broadened pattern matching, and added scheduled cleanup operations. Enhanced invalid buffer handling with explicit window closure and buffer deletion before instance mapping updates.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A rabbit hops through buffers deep,
Windows closing, cleanup's sweep!
TermClose rings with gentle cheer,
Resources freed, the code runs clear! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main fix: addressing terminal cleanup issues when the Claude process exits, which aligns perfectly with the changeset's objectives and file modifications.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Important

Action Needed: IP Allowlist Update

If your organization protects your Git platform with IP whitelisting, please add the new CodeRabbit IP address to your allowlist:

  • 136.113.208.247/32 (new)
  • 34.170.211.100/32
  • 35.222.179.152/32

Reviews will stop working after February 8, 2026 if the new IP is not added to your allowlist.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@lua/claude-code/file_refresh.lua`:
- Around line 103-105: The TermOpen autocmd uses the anchored pattern
'claude%-code$' while TermClose uses the unanchored 'claude%-code', causing
saved_updatetime to not be set for multi-instance buffers; update the TermOpen
autocmd (where saved_updatetime is set) to use the same unanchored pattern
'claude%-code' (or alternatively make TermClose use the anchored pattern) so
both autocmds consistently match multi-instance buffers and saved_updatetime is
always set/cleaned up.

Comment on lines +103 to +105
callback = function(args)
local buf_name = vim.api.nvim_buf_get_name(args.buf)
if buf_name:match('claude%-code') then
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Pattern inconsistency between TermOpen and TermClose.

The TermClose autocmd now uses claude%-code (substring match) at line 105, but the TermOpen autocmd at line 91 still uses claude%-code$ (end anchor). This inconsistency means:

  • For multi-instance buffers named claude-code-<path>, TermClose will match and clean up correctly
  • But TermOpen won't match them, so saved_updatetime won't be set when opening multi-instance terminals

Consider aligning the patterns:

Proposed fix
   vim.api.nvim_create_autocmd('TermOpen', {
     group = augroup,
     pattern = '*',
     callback = function()
       local buf = vim.api.nvim_get_current_buf()
       local buf_name = vim.api.nvim_buf_get_name(buf)
-      if buf_name:match('claude%-code$') then
+      if buf_name:match('claude%-code') then
         claude_code.claude_code.saved_updatetime = vim.o.updatetime
         vim.o.updatetime = config.refresh.updatetime
       end
     end,
🤖 Prompt for AI Agents
In `@lua/claude-code/file_refresh.lua` around lines 103 - 105, The TermOpen
autocmd uses the anchored pattern 'claude%-code$' while TermClose uses the
unanchored 'claude%-code', causing saved_updatetime to not be set for
multi-instance buffers; update the TermOpen autocmd (where saved_updatetime is
set) to use the same unanchored pattern 'claude%-code' (or alternatively make
TermClose use the anchored pattern) so both autocmds consistently match
multi-instance buffers and saved_updatetime is always set/cleaned up.

@greggh greggh merged commit 55c0cb5 into greggh:main Feb 4, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants