Environment
- Neovim: v0.12.3
- Plugin manager: lazy.nvim
- gemini-cli.nvim commit:
887fc46979e0a1e4e05035bcc83deb76164e91a2 (branch main)
- OS: Linux (WSL2)
Summary
plugin/gemini.vim automatically calls require('gemini').setup() as soon as the plugin is loaded:
" plugin/gemini.vim
if !exists('g:gemini_loaded')
lua require('gemini').setup()
let g:gemini_loaded = 1
endif
This conflicts with the standard lazy.nvim convention where the user is expected to call setup() themselves from their plugin spec's config function, e.g.:
return {
"jonroosevelt/gemini-cli.nvim",
config = function()
require("gemini").setup()
end,
}
Following that (very common) pattern results in setup() running twice on every startup — once automatically via plugin/gemini.vim, and once via the user's own config function.
Why this matters
M.setup() calls vim.fn.executable("gemini"), and if the gemini CLI binary isn't on $PATH, it falls into a branch that calls the blocking vim.fn.input("Gemini CLI not found. Install it now? (y/n): "). Since this executes automatically at plugin-load time (i.e. during Neovim startup), it:
- Blocks Neovim startup on a synchronous prompt before the UI is even fully drawn, rather than failing gracefully or deferring to a user command.
- Can be triggered twice in a row when the user also has a
config = function() require("gemini").setup() end in their lazy.nvim spec (a natural thing to write, since nothing in the README says not to), producing two sequential blocking prompts.
- In headless/scripted Neovim invocations (e.g.
nvim --headless -c '...', useful for CI, nvim -l scripts, or automation), this prompt has no way to be answered and hangs indefinitely until the process is killed.
Steps to reproduce
- Install with lazy.nvim using the "normal" pattern:
return {
"jonroosevelt/gemini-cli.nvim",
config = function()
require("gemini").setup()
end,
}
- Make sure the
gemini CLI binary is not installed / not on $PATH.
- Start Neovim.
Expected behavior
setup() should only run once, regardless of whether the user also calls it explicitly from their lazy.nvim config function (or it should not be auto-invoked from plugin/gemini.vim at all, leaving that entirely up to the user's config/lazy-loading setup, per standard plugin conventions).
- Missing the
gemini CLI shouldn't block Neovim startup with a synchronous prompt. Consider:
- Using
vim.notify(...) (non-blocking) instead of vim.fn.input(...), and/or
- Exposing an explicit
:GeminiInstall user command instead of prompting automatically, and/or
- Deferring the check with
vim.schedule() / VimEnter so it doesn't block startup, and skipping the interactive prompt entirely when running headless (#vim.api.nvim_list_uis() == 0).
Suggested fix
Remove the automatic require('gemini').setup() call from plugin/gemini.vim and let the plugin's own M.setup() be the single entry point that users call once from their plugin manager config (standard lazy.nvim convention). Alternatively, guard plugin/gemini.vim's auto-call so that if the user's own config already called setup(), it's a no-op (e.g. track an internal "already set up" flag inside M.setup() itself, not just via the vimscript-side g:gemini_loaded guard which doesn't protect against the lua-side call from config).
Separately, please consider not blocking on vim.fn.input() for the CLI-install prompt — it can hang indefinitely in headless/non-interactive Neovim sessions with no way to respond.
Environment
887fc46979e0a1e4e05035bcc83deb76164e91a2(branchmain)Summary
plugin/gemini.vimautomatically callsrequire('gemini').setup()as soon as the plugin is loaded:This conflicts with the standard lazy.nvim convention where the user is expected to call
setup()themselves from their plugin spec'sconfigfunction, e.g.:Following that (very common) pattern results in
setup()running twice on every startup — once automatically viaplugin/gemini.vim, and once via the user's ownconfigfunction.Why this matters
M.setup()callsvim.fn.executable("gemini"), and if thegeminiCLI binary isn't on$PATH, it falls into a branch that calls the blockingvim.fn.input("Gemini CLI not found. Install it now? (y/n): "). Since this executes automatically at plugin-load time (i.e. during Neovim startup), it:config = function() require("gemini").setup() endin their lazy.nvim spec (a natural thing to write, since nothing in the README says not to), producing two sequential blocking prompts.nvim --headless -c '...', useful for CI,nvim -lscripts, or automation), this prompt has no way to be answered and hangs indefinitely until the process is killed.Steps to reproduce
geminiCLI binary is not installed / not on$PATH.Expected behavior
setup()should only run once, regardless of whether the user also calls it explicitly from their lazy.nvimconfigfunction (or it should not be auto-invoked fromplugin/gemini.vimat all, leaving that entirely up to the user'sconfig/lazy-loading setup, per standard plugin conventions).geminiCLI shouldn't block Neovim startup with a synchronous prompt. Consider:vim.notify(...)(non-blocking) instead ofvim.fn.input(...), and/or:GeminiInstalluser command instead of prompting automatically, and/orvim.schedule()/VimEnterso it doesn't block startup, and skipping the interactive prompt entirely when running headless (#vim.api.nvim_list_uis() == 0).Suggested fix
Remove the automatic
require('gemini').setup()call fromplugin/gemini.vimand let the plugin's ownM.setup()be the single entry point that users call once from their plugin manager config (standard lazy.nvim convention). Alternatively, guardplugin/gemini.vim's auto-call so that if the user's own config already calledsetup(), it's a no-op (e.g. track an internal "already set up" flag insideM.setup()itself, not just via the vimscript-sideg:gemini_loadedguard which doesn't protect against the lua-side call fromconfig).Separately, please consider not blocking on
vim.fn.input()for the CLI-install prompt — it can hang indefinitely in headless/non-interactive Neovim sessions with no way to respond.