Repository navigation
docs: verify every README claim against the code and correct the ones it contradicts - #533
Conversation
Re-ran egm-bootstrap over lua/, plugin/ and scripts/, then an EGM drift pass, and fixed every claim the code contradicted or left uncovered. --- _Generated with [`xum`](https://github.com/coder/xum) • Model: `anthropic:claude-opus-5-5` • Thinking: `high`_
Ran each claim that the drift pass could not check from source in real Neovim 0.8 to 0.12, against the live server, Snacks at the pinned commit, and the scripts, then corrected the claims the runs did not support. --- _Generated with [`xum`](https://github.com/coder/xum) • Model: `anthropic:claude-opus-5-5` • Thinking: `high`_
The WebSocket shell clients are being removed in their own PR, which carries the refreshed scripts README. --- _Generated with [`xum`](https://github.com/coder/xum) • Model: `anthropic:claude-opus-5-5` • Thinking: `high`_
Take main's newer text where a peer PR rewrote a passage (#445 to #504). Keep a docs-gtz7 correction where both sides left it compatible. Drop the docs-gtz7 lockfile.update bullet and the "leaves that lock file on disk" claim, because #459 changed them. The corrections are verified against the code in the commits that follow.
Add what rejects a pending openDiff (Claude's close tools too) and say that nothing answers it when Neovim exits. Say that the commands of auto-setup exist after a startup script that waits lets the deferred setup run.
Checked each line that the branch changes against lua/claudecode/tools/*.lua
at origin/main. A call without arguments runs the tool with {} since #500, the
integration runner no longer skips command_args_spec.lua since #445, and the
getCurrentSelection bullet needs the #457 condition. The openFile recovery
read does not end Visual mode, which a probe confirmed.
At exit Neovim fires BufUnload for each loaded buffer before VimLeavePre. The BufUnload autocmd of the proposal buffer rejects its pending diff (diff.lua:1279), so the VimLeavePre cleanup finds none. A probe that fired VimLeavePre alone had hidden this.
Checked each line that the branch changes against lua/claudecode/*.lua at origin/main. Drop lockfile.update (removed by #459), the old mention-queue polling (removed by #454), the unified bufhidden=wipe claim (#469), the BufEnter pile-up claim (#478) and the integration runner skip (#445). Add TextChangedI and TextChangedP (#452).
Native close and get_active_bufnr adopt a reloaded terminal since #464, so drop the sentence that said they never adopt. Add the conditions that probes found for termopen under :silent!, the Snacks window position fallback and the config of an adopted terminal.
…erifier notes Name the CI job of each command and the jobs that Required needs. State the exit-code precedence of check-lib.sh and which modes download the TLC jar (only a plain run and --mutants). Say how a Lua repro exits under nvim -l and which scripts need the repo on runtimepath. List the release runner's stdout and file outputs. List the side effects of the 70 and 277 repros that the file did not name, and why the helper logs No global response sender.
…lete mock.lua is required by tests/unit/server/mock_spec.lua. The augroup and utils lists miss ClaudeCodeNativeAdopted, ClaudeCodeOpenFileNewFiles and map_terminal_suspend. An empty CLAUDE_CONFIG_DIR uses ~/.claude/ide. The Processes bullet misses the checkhealth --version call and the git rev-parse call. The selection bullet moves below the mention bullets.
#522 changed the integration runner, its README bullets and two comments in test.yml. The merge is clean. The README lines of this branch that name the runner are re-checked in the next commit.
…d fix seven wording findings A new-file diff in the current tab with on_new_file_reject = "keep_empty" deletes its proposal buffer when it is rejected. In Neovim's exit loop that stops BufUnload for the later buffers, so a second native diff reaches the VimLeavePre cleanup unanswered (Neovim 0.8.0 to 0.12.3, diff.lua:1171-1175). One pending diff and the unified layout are not affected. Also: set -e exits with the status of the failed command, the patched snacks toggle hides a visible terminal and focuses nothing, error_data counts when truthy, getCurrentSelection can adopt a Claude terminal after a plugin reload, the snacks_win_<id> augroup joins the lists, _accumulate joins the seam only when acc is not empty, and the when_windows_allowed citation names its file.
|
@codex review |
|
@codex security review |
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex Review: Didn't find any major issues. Nice work! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
🛡️ Codex Security ReviewSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
Resolve the README conflicts with #524 and #530. Main's listener and flush wording for visual selections stays. The root Editor state bullet keeps the verified augroup list and takes main's listener wording. The terminal.setup sentence in lua/claudecode/README.md now names the provider that the warning keeps (#530), which replaces the claim that the warning is wrong.
Pick up #506, which changes only .agents/skills/verify-claudecode-nvim. No README line of this branch cites a file that it changed.
|
@codex review |
|
@codex security review |
🛡️ Codex Security ReviewSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
|
Codex Review: Didn't find any major issues. 👍 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Resolve the scripts/README.md conflict with #531. The run-release-please.sh bullet keeps the verified text and adds main's clause that commonmark must be on the module path too (release-please-runner.js requires it at load). #526 changes only comments and dead window option assignments in terminal/snacks.lua, and no README line of this branch depends on them.
|
@codex review |
|
@codex security review |
🛡️ Codex Security ReviewSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 42ef1bd122
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…in a path with a space Codex P2 findings on 42ef1bd: - stop tries to remove the lock file and only logs a warning when it cannot (init.lua M.stop). A token mismatch in start does the same. - The headless auto-setup check used --cmd "set rtp^=$PWD", which Ex splits at a space in the checkout path (E518). The lua form takes the path as a string.
|
@codex review |
|
@codex security review |
🛡️ Codex Security ReviewSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
|
Codex Review: Didn't find any major issues. 👍 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
) ## Why The advisor on coder#533 found that three sentences in `scripts/README.md` say the plugin removes the lock file with no condition. The removal can fail. `lockfile.remove` returns an error when `os.remove` fails (for example in a read-only lock directory) and when `vim.fn.filereadable` reports the file as missing (the file is gone, or it exists but is unreadable; follow-up F19 fixes the unreadable case) (`lua/claudecode/lockfile.lua:208-232`). `stop` and the token mismatch path of `start` only log a warning then, so a lock file that the removal failed to delete stays (`lua/claudecode/init.lua:642-647`, `:605-608`). `README.md` and `lua/claudecode/README.md` already carry the condition. `ARCHITECTURE.md` has the same wording: a comment says `M.stop()` will "remove lock file", and the Lock File System section shows an unconditional `fs_unlink` in a `VimLeavePre` callback. The lock directory sentence for `repro_issue_277.sh` said "else `~/.claude/ide`". The default applies when `CLAUDE_CONFIG_DIR` is unset or empty (`lua/claudecode/lockfile.lua:11-18`), and `README.md` already says so. ## What changed Three bullets in `scripts/README.md`, one sentence each, and two lines in `ARCHITECTURE.md`: - `repro_issue_70_probe.lua` (older text on `main`). Other Claude CLIs see the lock file until `claudecode.stop()` removes it. New: when the removal fails, `stop` only logs a warning, so a lock file that the removal failed to delete stays. - `repro_issue_70.sh`. A probe stopped by SIGTERM "still tries to remove" its `PORT.lock`. When that fails, `stop` only logs a warning, so a lock file that the removal failed to delete stays. A SIGKILL leaves the file behind, as before. - `repro_issue_277.sh`. The plugin "removes the lock, or only logs a warning when it cannot". The lock directory is `$CLAUDE_CONFIG_DIR/ide`, or `~/.claude/ide` when that variable is unset or empty. I added the citation `[lua/claudecode/init.lua:M.stop]` to the first bullet. - `ARCHITECTURE.md`, Resource Cleanup. The comment now reads `-- Stop server, try to remove lock file (only logs a warning when it cannot)`. The file has no `[file:symbol]` citations, so I added none. - `ARCHITECTURE.md`, Lock File System. One sentence after the code block: the real cleanup runs from `init.lua`, whose `VimLeavePre` autocmd calls `stop` when the server runs, `stop` calls `lockfile.remove`, and `stop` only logs a warning when the removal fails, so a lock file that the removal failed to delete stays. ## Scope I grepped every tracked Markdown file for lock-file removal wording (remove, delete, unlink, clean up, stale, leaves). The other READMEs already carry the condition: `README.md:1126` and `:1154-1155`, and `lua/claudecode/README.md:109-111` and `:196`. The `ARCHITECTURE.md` sketch (line 55) reads as how the plugin works today and not as an illustration. It sits under the heading `lockfile.lua` and no text calls it an example. It is also wrong: `lockfile.lua` has no `VimLeavePre` autocmd and removes the file with `os.remove` in `lockfile.remove` (`lua/claudecode/lockfile.lua:221`), and the exit cleanup is in `init.lua` (`lua/claudecode/init.lua:514-518`). So I left the code block as it is and added the one sentence. I did not fix the other lines of the sketch (`write_file` and `fs_rename` are not in `lockfile.lua` either). That is a wider rewrite of the section. Not changed: - `.agents/skills/verify-claudecode-nvim/features/server.md:9` and `:12` describe the checked working case ("deletes `<port>.lock`"). They are test expectations. - `scripts/repro_issue_70_probe.lua:84` has the code comment `-- removes the lock file`. It is code and not a README. ## Blast Radius Two documentation files: three lines of `scripts/README.md`, and two lines of `ARCHITECTURE.md` (one changed, one added). Nothing loads them. A wrong sentence here misleads a reader and breaks no behavior. ## Verification I probed `scripts/repro_issue_70_probe.lua` on Neovim 0.12.3 in an isolated home (`env -i`, private `HOME`, `XDG_*` and `CLAUDE_CONFIG_DIR`, the stub `claude` first on `PATH`, provider `none`). Each case signalled only the `nvim` that it started. | Case | Result | |---|---| | Stop file | exit 2, 0 lock files left (`stop` removed it) | | SIGTERM | exit 1, 0 lock files left, `Claude Code integration stopped` logged | | Read-only lock directory, then stop file | exit 2, 1 lock file left (the removal failed, the file stays) | | SIGKILL | 1 lock file left | In the read-only case the probe prints no warning. `logger.warn` runs through `vim.schedule` (`lua/claudecode/logger.lua:109-120`), and the probe calls `os.exit` right after `stop()`. So the README says what `stop` does (it logs a warning) and does not say that the probe shows it. - Citation check over the seven READMEs: 762 citations, 1 flagged. The flagged one is `[plugin/claudecode.lua:pcall(require, "claudecode")]`, an expression that `main` already cites. - `mise run format-check`: exit 0 (355 files, 0 changed). - `mise run all`: exit 0 (1682 successes, 0 failures, 0 errors, 24 pending, `luacheck` 0 warnings and 0 errors in 178 files). - The Codex code review of round 2 raised one P3: `lockfile.remove` also fails when the file is already gone (or unreadable; see F19) (`lua/claudecode/lockfile.lua:215-216`), so a failed removal does not always leave a file. The three sentences that said "the file stays" now say that a lock file that the removal failed to delete stays. - The commits after the first are docs only. No test, script or CI file reads `ARCHITECTURE.md` (grep over `tests`, `scripts` and `.github`). For them I ran `mise run format-check` (exit 0, 355 files, 0 changed) and the citation check (762 citations, same 1 flagged). I did not run `mise run all` again. CI runs the full test suite on the final head. - `git merge-tree --write-tree` of the head and `origin/main` is clean. --- _Generated with [`xum`](https://github.com/coder/xum) • Model: `anthropic:claude-sonnet-5-5` • Thinking: `xhigh`_
… per lookup (coder#539) ## Why The plugin's code text and debug log must say what the code does. Three small places did not. A client with a wrong token was logged as authenticated. One git lookup started two git processes. A comment gave the wrong scope for the PRNG seed. ## What changed 1. **Authenticated log (`lua/claudecode/server/init.lua`).** `on_connect` runs at the TCP accept, before the handshake and the token check. With an auth token it logged `Authenticated WebSocket client connected` there, so a client with a wrong token got that line before the server rejected it. `on_connect` now logs `WebSocket client connected, awaiting authentication`. `on_open` runs after the handshake passed the check and now logs `Authenticated WebSocket client connected`. The line without a token (`WebSocket client connected (no auth)`) is the same. 2. **One git process per lookup (`lua/claudecode/cwd.lua`).** `git_root` called `vim.fn.systemlist` inside a `pcall` only to see whether it takes a list, then called it again for the result. It now keeps the result of the first call. The shell-string fallback for a `systemlist` that refuses a list is the same. 3. **PRNG comment (`lua/claudecode/server/tcp.lua`).** The comment said the PRNG is seeded once per process. `rng_seeded` is a module local, so it is seeded once per load of the module. I fixed the comment and left the seeding alone. A second seed in one process is harmless, because it mixes in the time and a sub-second source. Neovim loads the module once, so a fresh Neovim still seeds once, which is all that coder#283 needs. A real once-per-process guard would need global state that nothing else uses. READMEs: `lua/claudecode/server/README.md` describes `on_open`, `on_connect` and the seeding scope. `lua/claudecode/README.md` says git runs at most once for each lookup (a missing folder or a nil start folder runs no git). The seeding line has the same text as the line on the `docs-gtz7` branch, so the two merge without a conflict. ## Scope No behavior changes except the two log lines and the number of git processes. The handshake, the token check and the shell fallback in `git_root` are untouched. I added no test for the comment, because it has no behavior to test. A real Neovim probe confirms its new claim (see Verification). ## Blast Radius - Debug log only: with an auth token, the line `Authenticated WebSocket client connected: <id>` moves from the TCP accept to after the handshake. Nobody parses it in this repo (I grepped code, tests, scripts, fixtures and docs). - `git_root`: one process fewer for each lookup. The result and the `shell_error` it checks come from the call that remains. - `covered.lock`: the diff touches three covered files (`cwd.lua`, `server/init.lua`, `server/tcp.lua`) and none of their covered blocks. `check.sh` printed STALE for the three file hashes only. It printed no changed block and no changed call site. The change cannot reach diff state, an openDiff answer, a disconnect or a diff command. `on_disconnect`, `M.stop` and the request handlers are unchanged. `on_connect` and `on_open` only gain or move a `logger.debug` call. `tcp.lua` changes a comment. `cwd.lua` is the terminal's git root lookup. The model passed (`main`: 89205 distinct states, `live-DisconnectedCallsAnswered`: 5269). `check.sh --record` wrote the new lock and `check.sh --hash-only` reports that it matches. ## Verification Red before the fix, green after (same specs, only the three `lua/` files swapped): | Spec | origin/main | with the fix | | --- | --- | --- | | `tests/unit/server/connect_log_spec.lua` (4 new cases: log order and no `Authenticated` for a TCP-only client or a wrong token) | 1 success, 3 failures | 4 successes | | `tests/unit/cwd_spec.lua` (5 new cases: git invocations per lookup) | 2 successes, 3 failures (2 runs, expected 1) | 5 successes | Real Neovim probes (loopback server with a raw TCP client, and a real git repository), before and after: - Wrong token: `server: Authenticated WebSocket client connected: client_1` was logged first, then `Rejected client_1: Invalid authentication token`. After the fix the wrong-token client has no `Authenticated` line. The right-token client gets it after `Client authenticated successfully`. Lines with `Authenticated` for the two clients: 2 before, 1 after. - `git_root` on a real repository: 2 git invocations before, 1 after. - `tcp.lua` seeding: 1 seed for one load and two port searches. 2 seeds after a reload of the module and one more search. Gates on the final commit, which merges `origin/main` (036427a) into the branch (private XDG folders): - `mise run all`: native exit 0. luacheck: 0 warnings / 0 errors in 180 files. busted: 1691 successes / 0 failures / 0 errors / 24 pending. treefmt: 0 files changed. - `mise run format-check`: native exit 0 (357 files, 0 changed). - Sibling specs (every spec under `tests/unit/server/`, `server_spec`, `server_tool_call_log_spec`, `cwd_spec`, `terminal_spec` and `tests/unit/terminal/`): 556 successes, 0 failures. - `scripts/run_integration_tests_individually.sh`: 331 successes, 0 failed, 0 errors. - `.agents/skills/verify-diff-lifecycle/check.sh --hash-only`: covered.lock matches the code. The merge with `origin/main` conflicted in `lua/claudecode/README.md` and `lua/claudecode/server/README.md`, where the README refresh (coder#533) rewrote the lines this PR edits. I kept main's text and reapplied this PR's two changes (the `at most once` wording and the `on_open` log). Two independent verifiers (Opus and GPT) checked the head before the merge with `origin/main`. Both found no introduced defect. They reran the red and green specs, reverted each code change alone to see the new specs fail, and ran real loopback clients against the server. Their wording findings are in the branch (the README line says "at most once", and the `on_open` comment says "with a token"). --- _Generated with [`xum`](https://github.com/coder/xum) • Model: `anthropic:claude-sonnet-5-5` • Thinking: `xhigh`_
Why
The goal is that every claim in the README contracts of this repository is true for the code at
main, and that each correction names its evidence. A contract is the README of one folder. It states what the code does and cites the function that does it. The branchdocs-gtz7corrected many claims at an old commit ofmain.mainhas moved since (peer PRs #445 to #522 rewrote several passages and changed the code). This PR mergesmaininto that work, re-checks every line that it changes against the current code, and fixes the lines that the peers made stale or that the merge joined into false text.What changed
Docs only, in seven README files. The branch has four parts.
The commits of
docs-gtz7(three content commits and a merge ofmain): a refresh of the contracts against the code, a pass that fixed the drift that the refresh left, and a pass that corrected claims which runtime probes disproved.Five merge commits of
main(the second for test: start the runner's spec Neovims with tests/minimal_init.lua #522, the third for fix(selection): keep the release of a visual selection after a plugin edits another line or writes the file #524 and fix(terminal): name the provider that setup keeps for an invalid provider value #530, the fourth for fix(skills): check the state dir once, not each run.env, and resolve TMPDIR once #506, the fifth for fix(scripts): read the Unreleased draft with commonmark.js and refuse what it does not read #531 and test(terminal): test the snacks guards that no test reached, and drop four dead window option assignments #526). Where a peer PR anddocs-gtz7both changed a passage,main's text won. Adocs-gtz7correction stayed only where it is still true.Nine correction commits. Six verifier agents, one per file or half file, checked every line that this diff changes against the code. They ran headless Neovim 0.12.3 probes (one on 0.10.4) where reading did not decide the claim. I applied their corrections in commits that group the files: server, root and plugin, tools, lua, terminal, scripts, the main-text fixes, and one for the exit sentences and the last seven findings. A second verifier then found one false sentence (the exit sentence below) and seven wording findings, which that last commit fixes.
One commit for two P2 findings of the Codex code review on
42ef1bd1. First,stopand the token mismatch instarttry to remove the lock file and only log a warning when that fails (lua/claudecode/init.lua:642-647,:605-608), so three sentences inREADME.mdnow say "tries to". Second, the headless auto-setup check inplugin/README.mdused--cmd "set rtp^=$PWD", which Ex splits at a space in the checkout path. I ran it in/…/with space/repoon Neovim 0.12.3: it fails withE518and prints0. Thelua vim.opt.rtp:prepend(vim.fn.getcwd())form prints2, and0without the auto-setup line, as the README says.Per file, with the number of claims checked and the result:
README.md(Repository Blueprint)plugin/README.mdlua/claudecode/README.mdlua/claudecode/server/README.mdlua/claudecode/terminal/README.mdlua/claudecode/tools/README.mdscripts/README.mdA false claim was true at the old base or never true. An incomplete claim leaves out a condition that the code has. The row for
scripts/README.mdlists the seven items of the #462 verifiers (one more was misleading). The 541 claims of the first six rows split into 480 true, 20 false, 40 incomplete and 1 unverified.Re-sync items after the peer PRs
provider).lua/claudecode/README.mdsaid that an invalidproviderkeeps the previous value "although the warning says Defaulting to 'native'".mainnow warnsKeeping '<provider>'(lua/claudecode/terminal.lua:483-488). The sentence says what the warning names now. The defect is gone from the list of code defects below.run-release-please.shbullet ofscripts/README.mdkeeps the verified text and addsmain's clause thatcommonmarkmust be on the module path too. The runner requires it at load (scripts/release-please-runner.js:27). The Communique, Prettier and output code that the runner bullet cites did not change.lua/claudecode/terminal/snacks.lua. No line of this PR depends on them.main's text won in both, and the rootEditor statebullet keeps the verified autocmd group list withmain's listener wording (lua/claudecode/selection.lua:watch_selection_buffer,note_visual_edit). The selection claims that this PR changes (selection_changedpositions,selection.luainternals) do not depend on the code that fix(selection): keep the release of a visual selection after a plugin edits another line or writes the file #524 changed.README.mdno longer says thatstartleaves the lock file on disk after a token mismatch:startremoves it and stops the server (lua/claudecode/init.lua:603-619). The System Verification bullet aboutCLAUDE_CONFIG_DIRandtests/lockfile_test.luais gone: the test hides the caller's value and stays in a private home (tests/lockfile_test.lua:340-355,:439-442).lockfile.updateis removed fromlua/claudecode/README.md: the module has no such function. Thestartandstopbullets use the text of fix(lockfile): report failed removals and clean up on token mismatch #459, andstopis described as an attempt to remove the lock file (init.lua:635-670).lua/claudecode/tools/README.mdis the text ofmain. The claim that the recovery read does not end Visual mode stays. A probe confirmed it in both forms: plain Visual mode, and Visual mode that CTRL-O started. The read runs throughnvim_buf_call, so the mode stays on (lua/claudecode/tools/open_file.lua).scripts/lib_claude.shor another deleted file (a grep over the seven files finds none).Corrections per file
README.md
openDiffnow includes Claude'sclose_tabandcloseAllDiffTabscalls, which reject it throughclose_diff_by_tab_name(lua/claudecode/diff.lua:2040-2044,:2105-2107,lua/claudecode/tools/close_tab.lua:53,lua/claudecode/tools/close_all_diff_tabs.lua:30).BufUnloadfor each loaded buffer beforeVimLeavePre, and the proposal buffer'sBufUnloadautocmd rejects its pending diff (lua/claudecode/diff.lua:1279-1285). So with one pending diff the rejection runs before theVimLeavePrecleanup. With two or more pending native diffs there is one exception: the reject of a new-file diff in the current tab withdiff_opts.on_new_file_reject = "keep_empty"(the default) deletes its proposal buffer (diff.lua:1171-1175,:1523-1524), Neovim's exit loop then stops firingBufUnload, and the cleanup removes the other diffs with no answer. Probes on Neovim 0.8.0, 0.9.5, 0.10.4, 0.11.5 and 0.12.3 show both cases, and theunifiedlayout answers every diff. The sentence states both. A fix PR (F13) follows, see "Defects in the code".startremoves the lock file on a token mismatch (see above).:checkhealth claudecode(<cli> --version,lua/claudecode/health.lua:43-66) and thegit rev-parseofterminal.git_repo_cwd(lua/claudecode/cwd.lua:28-42).CLAUDE_CONFIG_DIRset but empty uses~/.claude/ide(lua/claudecode/lockfile.lua:11-18). Three lines say so now.lua/andplugin/(ClaudeCodeShutdown,ClaudeCodeSelection,ClaudeCodeMCPDiff,ClaudeCodeDiffCleanup,ClaudeCodeNativeAdopted,ClaudeCodeOpenFileNewFiles, and onesnacks_win_<id>per Snacks terminal whose split the plugin re-creates,lua/claudecode/terminal/snacks.lua:259), thenvim_buf_attachlisteners (lua/claudecode/selection.lua:175-191) and the"unified"highlight groups (lua/claudecode/diff_inline.lua:33-36).plugin/README.md
:sleeporvim.wait()) lets the deferredsetuprun. They do not exist when the-ccommands andVimEnterrun. Headless probes on Neovim 0.12.3 (plugin/claudecode.lua:13-17).sourcedoing nothing, the version error on Neovim older than 0.8, the failed module load shown once, the auto-setup global read twice, and the error from the deferredsetup.lua/claudecode/README.md: 23 corrections with evidence
~and~/.... A path such as~user/xstays as it is. Evidence: lua/claudecode/init.lua:1113-1117, lua/claudecode/utils.lua:167-181.lua/claudecode/server/README.md: 13 corrections with evidence
closingafter on_close. On_close only removes the client (README line on client states says it never becomesclosed) Evidence: lua/claudecode/server/client.lua:363-371, tcp.lua:227-228, tcp.lua:275-283.closedwhen a keepalive window passes with no write progress Evidence: lua/claudecode/server/client.lua:459-466, client.lua:140-144.connectedafter EOF) Evidence: lua/claudecode/server/tcp.lua:209-217, tcp.lua:255-294, probe-server/events.log client_8, client_9.Itreads as process_data or the Close frame. Process_data does check the whole message Evidence: lua/claudecode/server/frame.lua:156-168, client.lua:184-188.lua/claudecode/terminal/README.md: 5 corrections with evidence
lua/claudecode/tools/README.md: 14 corrections with evidence
params.arguments or {}, so no Lua error and no -32000 (probe p1: openFile/saveDocument -32602, getDiagnostics []). Also contradicted line 17. Evidence: lua/claudecode/tools/init.lua:88, lua/claudecode/server/init.lua:357, probes/p1_static.out.{ result = ... }. Also joins the hard-wrapped bullet like the rest of the file. Evidence: lua/claudecode/tools/close_tab.lua:26-33, lua/claudecode/tools/init.lua:180-182, lua/claudecode/server/init.lua:387.~user/...unchanged. Evidence: lua/claudecode/utils.lua:167-181, lua/claudecode/tools/open_file.lua:547.scripts/README.md: 7 items of the #462 verifiers, each checked against the scripts
.github/workflows/test.yml(unit-tests,integration-tests,covered-lock), says thatintegration-testsruns the runner twice (the second time with aTMPDIRthat holds a space and a%), and says thatRequiredneeds onlyunit-testsandintegration-tests(test.ymllines 52-80, 98-167, 215-234).tla/check-lib.shexit precedence: 2 wins over 1, and 1 wins over 3. A stale lock plus a broken rule exits 1.--hash-onlyexits 0 or 3, and--recordexits 0. A script that sources the lib and ends withouttla_mainturns an exit 0 into exit 2. Probed with a fakecurland a fake TLC: default with a broken rule and a stale lock gave rc=1, default with a pass and a stale lock rc=3, a brokenTypeOKrc=2,--recordon a stale lock rc=0 (scripts/tla/check-lib.sh:81-84,:226-246,:313-333,:406-419).tla_initcomes right afterSKILLandMODEL, beforecovered_block(.agents/skills/verify-diff-lifecycle/check.sh:15-29,scripts/tla/check-lib.sh:461).run-release-please.shprints nothing itself, and exits 1 with no message whenrelease-pleaseis missing. The runner's stdout and file outputs are listed: release-please's own log lines go to stdout (info and debug) and stderr (warnings and errors), thekey=valuelines go toGITHUB_OUTPUTor to stdout when it is unset, and--dry-runprints JSON after the log lines and still runs Communique. Probed without a token and without network: wrapper rc=1 with no output, andError: GITHUB_TOKEN must be set(scripts/release-please-runner.js:487-492,:555,:590,:614).--recordand--hash-onlyexit before the TLC jar is fetched, so they never download it and need nojava. A plain run and--mutantsdo. Probe with an empty cache and a fakecurl:--hash-onlyand--recordmade 0curlcalls, a plain run and--mutantsmade 1 and exited 2 (scripts/tla/check-lib.sh:452-453,:147-151).nvim -lan uncaught error printsE5113and exits 1,cquit Nandos.exit(N)exit N, and a bare file name run fromscripts/fails withmodule 'claudecode.diff' not found. In the:luafileform of CI an uncaught error falls through tocquit 2(probes on Neovim 0.12.3, and-lexit 1 on 0.9.5, 0.10.4 and 0.11.5).repro_issue_70.shandrepro_issue_277.shside effects that the file did not list: work dir names, theatt-homefolder, the empty/tmp/agent-tty/<8 hex>socket folder and thehomes.jsonentry thatagent-ttyleaves, the inherited environment, the three background probes of 70 and theirPORT.lockfiles (a SIGKILL leaves the lock), the unpinned diffview.nvim clone of 277, the state and cache files ofNVIM_APPNAME=issue-277, theperltimeouts, and the nested copy under an existingissue277-artifacts-latest. A full run of 277 with private dirs took 32 s. A SIGKILL run left the lock file and 3 processes untilagent-tty destroy.manual_test_helper.luacalls the handler itself, so no response sender is stored for its coroutine. Any resolution after the handler yields (accept, reject, orqa!) logsNo global response sender found for coroutine. It is expected and harmless (all four CI-form runs exited 0).Scope
covered.lockdoes not change.scripts/README.mdaboutrepro_issue_218.shstay as they are onmain. PR fix(scripts): stop repro_issue_218.sh from rewriting a tracked file and leaking its temp dir #458 owns them, and its merge will change them.server/mock.luais required bytests/unit/server/mock_spec.lua, the augroup andutils.lualists, the emptyCLAUDE_CONFIG_DIR, and the Processes bullet.lua/claudecode/server/README.mdthat a client whose EOF the server read in the same read as its request is handled as the code says. Six probe tries did not produce that case. The sentence is a softening, so I kept it.closedoes not prevent a hang at exit. A probe saw the hang with and without aclose, so the probe does not prove that the buffer delete causes it. I did not open Terminal buffer deletion hangs with a pending write neovim/neovim#42508 (the host has no network).Defects in the code that the verifiers found
These need a code fix and a test, so they are not in this docs PR.
unifieddiff drops one trailing empty line of the proposal:"a\n\n"is accepted as"a\n"(lua/claudecode/diff_inline.lua:44-52and:531). The native layout is not affected. A probe shows it. The README says the accepted text is the proposal lines that setup computed.lua/claudecode/server/tcp.lua:19says the PRNG is seeded once per process. It is seeded once per load of the module.lua/claudecode/server/init.lua:59-60logs "Authenticated WebSocket client connected" fromon_connect, before the authentication check runs.lua/claudecode/cwd.lua:36-42runs the samegit rev-parsetwice.diff_opts.on_new_file_reject = "keep_empty"(the default). On:qa!its reject deletes its proposal buffer (lua/claudecode/diff.lua:1171-1175,:1523-1524), Neovim's exit loop stops firingBufUnload(src/nvim/main.c, thebufref_validcheck), and theVimLeavePrecleanup removes the second diff with no answer. Reproduced on Neovim 0.8.0, 0.9.5, 0.10.4, 0.11.5 and 0.12.3, with and without the server. A separate PR (F13) will make exit answer every pending diff. It will change the exit sentences of this PR: the openDiff bullet inREADME.md(Global Invariants, the sentence that starts "When Neovim exits") and the Augroups bullet inlua/claudecode/README.md(the sentences aboutBufUnloadand the exception).Blast Radius
Seven README files. Nothing loads them at runtime. A wrong correction here misleads a reader but breaks no behavior.
Verification
lua/claudecode/README.md). Each checked every claim that the diff adds or changes against the code, and every[file:symbol]citation, with file and line evidence. Their findings, edits and probe scripts are in the evidence folder of the run.bcacd14c(134 sentences and all seven scripts items, with probes on Neovim 0.8.0 to 0.12.3). It found one false sentence (the exit sentence, now fixed with its exception) and seven wording findings (fixed). It found no other false claim.[plugin/claudecode.lua:pcall(require, "claudecode")], an expression thatmainalready cites in that README.mise run all: exit 0 on the final heade3e48af1(1682 successes, 0 failures, 0 errors, 24 pending,luacheck0 warnings and 0 errors in 178 files).mise run format-check: exit 0 on the final head (355 files, 0 changed). 1676 successes, 0 failures, 0 errors, 24 pending.luacheckreports 0 warnings and 0 errors in 178 files. The format step changes 0 files.git merge-tree --write-treeof the head andorigin/main(3a0bb769) is clean.lua/claudecode/README.mdand merged two conflict hunks. I checked that sentence and the merged bullets againstlua/claudecode/terminal.luaandlua/claudecode/selection.luaata41254a4. I did not run a verifier agent over the merge delta.Generated with
xum• Model:anthropic:claude-sonnet-5-5• Thinking:xhigh