Skip to content

Follow-ups from #375-#384: accepted-diff hand-over format, selection and window edge cases #385

Closed

Description

@ThomasK33

Verification of #375 to #384 (the fixes for #374 and #363) found these. Each one is on main before those PRs too, or is a narrow case the PRs did not claim to cover. Items 1 to 3 come first.

  1. Accepted-diff hand-over keeps the buffer's file format (fix(diff): let :ClaudeCodeCloseAllDiffs finish an accepted diff #376). :ClaudeCodeCloseAllDiffs puts an accepted diff's text into the file's buffer. The buffer keeps 'fileformat', 'fileencoding' and 'bomb', so a CRLF proposal in a dos buffer is written as \r\r\n, and a € handed into a latin1 buffer is written with a conversion error. No text is lost: the user sees ^M before :w.
  2. Hand-over messages give the wrong reason (fix(diff): let :ClaudeCodeCloseAllDiffs finish an accepted diff #376). A swap file from another Neovim (E325 inside bufload), a failed nvim_buf_set_lines, or a ClaudeCodeDiffClosed handler that accepts a diff during the loop all print "its buffer has unsaved changes or cannot be written". A new file in a missing folder fails :w with E212 and needs a :w ++p hint. A failed hand-over still leaves buflisted/bufhidden changed, and fixeol=false stays after a hand-over.
  3. A rejected diff whose client is gone is never cleared. :ClaudeCodeCloseAllDiffs skips it. A full plugin reload also leaves an accepted diff's proposal buffer open but untracked.
  4. Selection tracking.
    • A <cmd>ClaudeCodeSend mapping in Select mode sends without a range (visual_commands treats only v, V and CTRL-V as Visual).
    • With 'virtualedit' all, Neovim yanks trailing spaces that the sent text lacks.
    • On Neovim 0.11+, C1 controls and format characters (U+200B) are their own character like TAB, but the plugin joins them with a following combining mark.
    • Blockwise selections are sent as one contiguous span, not the rectangle.
    • PROTOCOL.md's exclusive paragraph does not say that an end on an empty row is character 1.
  5. openFile and window choice.
    • A register prefix ("a) looks like Normal mode, so the user's next command (p) acts in the opened file. Documented, not fixable from the mode alone.
    • i<C-o>v takes the normal path, and Insert mode can resume in the opened file.
    • Previewing the buffer a diff window shows opens a closed diff fold in the user's window.
    • With only the preview window and a terminal, openFile and openDiff split the 12-line preview window.
    • preview: true with makeFrontmost: false, when the main window already shows the file, leaves no selection on.
    • With no editor window, makeFrontmost: false still moves focus to the split it creates.
    • The legacy diff.open_diff fallback (wincmd t/l) has no preview-window check. Nothing in the plugin calls it.
    • Doc gaps: lua/claudecode/README.md Diffs line omits the new-tab and fallback-split paths, and tools/README.md names only file-explorer sidebars (the code also skips outline sidebars).
  6. Outbound and inbound UTF-8. A buffer name with invalid bytes reaches Claude as U+FFFD, so Claude cannot reopen that exact name. The inbound frame check (server/utils.lua is_valid_utf8) is looser than the strict outbound utils.valid_utf8 (accepts overlong forms, surrogates, F5-FF).
  7. verify-claudecode-nvim skill. Under a default parent dir with a default ACL, a new $OUT is briefly 770 before chmod 700 (empty at that time). SKILL.md still says the proof takes about 30 s (now 45 s).
  8. CI runs busted in file order only. --shuffle with a printed seed would catch new order dependence.

Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: xhigh

Activity

  1. self-assigned this
    on Nov 1, 2026
  2. ThomasK33 commented on Nov 1, 2026

    @ThomasK33
    MemberAuthor

    All items are handled on main:

    1. Items 1 to 3 (accepted-diff hand-over format, messages, a rejected diff whose client is gone): fix(diff): hand accepted text over in the buffer's format, and close rejected diffs #392, merged as c05a629. It also re-records covered.lock, which fix(open_file): keep the user's Visual mode, unsaved changes and focus #387 had left stale for open_file.lua.
    2. Item 4 (selection tracking): fix(selection): count characters as Neovim does, and take the visual path in Select mode #388, merged as 6482ed6. Blockwise selections stay one contiguous span and 'virtualedit' spaces are not sent. Both are documented.
    3. Item 5 (openFile and window choice): fix(open_file): keep the user's Visual mode, unsaved changes and focus #387, merged as c9c4b07, and fix(diff): keep openDiff and diff.open_diff out of the preview window #391 (openDiff and diff.open_diff stay out of the preview window), merged as 97f698f. The "a register prefix stays documented, because the mode alone cannot show it.
    4. Item 6, inbound: fix(server): reject ill-formed UTF-8 in inbound frames with 1007 #390, merged as bf80d11. Ill-formed UTF-8 in a frame now gets Close 1007. Outbound: no change. A buffer name with invalid bytes still reaches Claude as U+FFFD, as lua/claudecode/server/README.md documents.
    5. Items 7 and 8 (the verify skill and --shuffle in CI): ci(test): shuffle the unit suite with a printed seed, and create the vcn evidence dir 0700 #386, merged as f8877ba.

    Verification found more edge cases. They are tracked in #393.


    Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: high

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

needs-triageAwaiting maintainer triage

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions