feat(vim): add known_human checkpoint plugin#1052
Conversation
Adds a Vimscript plugin that fires git-ai checkpoint known_human on file save with 500ms debounce per git repo root. Uses Vim 8+ async job API (job_start/ch_sendraw) with synchronous fallback for older Vim. No auto-install; installer surfaces manual steps for native packages, vim-plug, and Vundle. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| message: concat!( | ||
| "Vim: Automatic installation is not supported. ", |
There was a problem hiding this comment.
🔴 VimInstaller's install_extras message is silently dropped due to missing keyword triggers
The VimInstaller's install_extras returns an InstallResult with changed: false and a message starting with "Vim: Automatic installation is not supported. Install the plugin using one of these methods:...". In the display logic at src/commands/install_hooks.rs:570-588, results are only shown if result.changed is true, or if the message contains "already", "Unable", or "manually". The Vim message contains none of these keywords, so all four display conditions fail and the manual installation instructions are silently swallowed. Users who have Vim installed will see zero output for Vim during git-ai install-hooks, making the plugin integration completely undiscoverable.
Relevant display conditions in install_hooks.rs:570-588
result.changed && !dry_run → false (changed=false)
result.changed && dry_run → false
result.message.contains("already") → false
result.message.contains("Unable") || result.message.contains("manually") → false
Compare with JetBrains' fallback message which includes both "Unable" and "manually": "{}: Unable to automatically install plugin. Please install manually from: {}" at src/mdm/agents/jetbrains.rs:120-123.
Was this helpful? React with 👍 or 👎 to provide feedback.
…tection, and editor identity
| if has('job') && has('channel') | ||
| " Vim 8+ async job API | ||
| let l:opts = { | ||
| \ 'in_io': 'pipe', | ||
| \ 'out_io': 'null', | ||
| \ 'err_io': 'null', | ||
| \ } | ||
| let l:job = job_start(l:cmd, l:opts) | ||
| if job_status(l:job) ==# 'run' | ||
| let l:chan = job_getchannel(l:job) | ||
| call ch_sendraw(l:chan, l:payload) | ||
| call ch_close_in(l:chan) | ||
| endif | ||
| else | ||
| " Fallback: synchronous (Vim < 8.0) | ||
| let l:shell_cmd = join(map(copy(l:cmd), 'shellescape(v:val)'), ' ') | ||
| call system(l:shell_cmd, l:payload) | ||
| endif |
There was a problem hiding this comment.
🔴 Checkpoint command blocks Neovim UI because Neovim's async job API is not used
The plugin checks has('job') && has('channel') at line 113 to decide whether to use async execution. In Neovim, both has('job') and has('channel') return 0 (Neovim uses jobstart()/chansend() instead of Vim 8's job_start()/ch_sendraw()). This causes the code to fall through to the synchronous system() call at line 128, which blocks the editor for the entire duration of git-ai checkpoint. The plugin already detects Neovim at line 77 for the JSON payload, so this is an oversight in the execution path. For Neovim, the code should use jobstart() + chansend() + chanclose() for non-blocking execution.
| if has('job') && has('channel') | |
| " Vim 8+ async job API | |
| let l:opts = { | |
| \ 'in_io': 'pipe', | |
| \ 'out_io': 'null', | |
| \ 'err_io': 'null', | |
| \ } | |
| let l:job = job_start(l:cmd, l:opts) | |
| if job_status(l:job) ==# 'run' | |
| let l:chan = job_getchannel(l:job) | |
| call ch_sendraw(l:chan, l:payload) | |
| call ch_close_in(l:chan) | |
| endif | |
| else | |
| " Fallback: synchronous (Vim < 8.0) | |
| let l:shell_cmd = join(map(copy(l:cmd), 'shellescape(v:val)'), ' ') | |
| call system(l:shell_cmd, l:payload) | |
| endif | |
| if has('nvim') | |
| " Neovim async job API | |
| let l:job = jobstart(l:cmd, {'on_exit': {-> 0}}) | |
| if l:job > 0 | |
| call chansend(l:job, l:payload) | |
| call chanclose(l:job, 'stdin') | |
| endif | |
| elseif has('job') && has('channel') | |
| " Vim 8+ async job API | |
| let l:opts = { | |
| \ 'in_io': 'pipe', | |
| \ 'out_io': 'null', | |
| \ 'err_io': 'null', | |
| \ } | |
| let l:job = job_start(l:cmd, l:opts) | |
| if job_status(l:job) ==# 'run' | |
| let l:chan = job_getchannel(l:job) | |
| call ch_sendraw(l:chan, l:payload) | |
| call ch_close_in(l:chan) | |
| endif | |
| else | |
| " Fallback: synchronous (Vim < 8.0) | |
| let l:shell_cmd = join(map(copy(l:cmd), 'shellescape(v:val)'), ' ') | |
| call system(l:shell_cmd, l:payload) | |
| endif |
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
agent-support/vim/) that firesgit-ai checkpoint known_human --hook-input stdinon file save with 500ms debounce per git repo rootBufWritePostautocmd +timer_start(500, ...)for async debouncejob_start/ch_sendraw) for non-blocking git-ai calls; falls back to synchronoussystem()on Vim < 8.0VimInstallerRust struct that detects Vim and surfaces manual install instructionsManual install steps (for docs site)
Native packages (Vim 8+)
vim-plug (
~/.vimrc)Vundle (
~/.vimrc)Add to
.vimrc:set rtp+=~/.vim/bundle/git-ai/agent-support/vimTest plan
cargo clippy -- -D warningspassescargo testpasses🤖 Generated with Claude Code