Lightweight Neovim plugin connecting to AI agents via ACP (Agent Client Protocol).
- Connect to AI agents (OpenCode, Codex) via ACP protocol
- Floating prompt window with context capture
- Streaming response display
- Multi-session support with persistence
- Project-scoped sessions (git-aware, with cwd fallback)
{
"assagman/ghost.nvim",
event = "VeryLazy",
opts = {
backend = "opencode", -- or "codex"
},
keys = {
{ "<leader>aq", desc = "Ghost: Open AI prompt" },
{ "<leader>aq", mode = "v", desc = "Ghost: Open AI prompt with selection" },
{ "<leader>ar", desc = "Ghost: Toggle response window" },
{ "<leader>ag", "<cmd>GhostStatus<cr>", desc = "Ghost: Show status" },
},
cmd = { "GhostStatus", "GhostClear", "GhostReconnect", "GhostResponse", "GhostResponseClose", "GhostList" },
}use {
"assagman/ghost.nvim",
config = function()
require("ghost").setup({
backend = "opencode",
})
end
}Ghost supports two ACP backends:
| Backend | Subprocess Command | Auth |
|---|---|---|
opencode |
opencode acp |
Configured via opencode itself |
codex |
bunx -y @zed-industries/codex-acp |
CODEX_API_KEY or OPENAI_API_KEY env var |
- Install OpenCode
- Configure ghost:
require("ghost").setup({ backend = "opencode", -- default -- acp_command = "opencode", -- optional: override binary path })
-
Install bun (required to run
bunx):curl -fsSL https://bun.sh/install | bash -
Set API key (choose one):
export CODEX_API_KEY="your-api-key" # or export OPENAI_API_KEY="your-api-key"
-
Configure ghost:
require("ghost").setup({ backend = "codex", })
require("ghost").setup({
-- Backend: "opencode" or "codex"
backend = "opencode",
-- Agent/mode name (nil = backend default)
-- Options: "NULL", "plan", "explore", "general", etc.
agent = nil,
-- Model name/id (nil = backend default)
-- Examples: "gpt-4.1", "o1", "claude-sonnet-4-20250514"
model = nil,
-- Keybind to open prompt
keybind = "<leader>aq",
-- Enable autoread (buffers reload when agent edits files)
autoread = true,
-- Prompt window size (as fraction of editor)
window = { width = 0.6, height = 0.3 },
-- Response window size
response_window = { width = 0.7, height = 0.5 },
})| Command | Description |
|---|---|
:GhostStatus |
Show backend, connection, errors |
:GhostReconnect |
Reconnect to ACP subprocess |
:GhostClear |
Clear stale requests |
:GhostResponse |
Toggle response window |
:GhostResponseClose |
Close response window |
:GhostList |
List and switch sessions |
| Key | Mode | Action |
|---|---|---|
<leader>aq |
n | Open AI prompt (new session) |
<leader>aq |
v | Open AI prompt with selection |
<leader>ar |
n | Toggle response window |
<leader>ag |
n | Show Ghost status |
Ghost stores sessions per-project under ~/.local/share/nvim/ghost/projects/<project>/sessions/.
- Git repositories: Uses the git root directory name as the project key
- Non-git directories: Uses the full cwd path (sanitized) as the project key
Run :checkhealth ghost to verify your setup:
:checkhealth ghostThis checks:
- Neovim version
- Backend executable availability
- Git availability (for session persistence)
- Snacks.nvim availability (optional, for enhanced picker)
- ACP connection status
- Snacks.nvim: Enhanced session picker with rename/delete keybinds
- Without Snacks: Falls back to
vim.ui.selectfor session management
- Without Snacks: Falls back to
Run unit tests from Neovim:
:lua require('ghost.test').unit_tests()Run interactive tests:
:lua require('ghost.test').test_connection()
:lua require('ghost.test').test_prompt("Say hello")- codex: Ensure
bunxis in$PATH(install bun first) - opencode: Ensure
opencodebinary is in$PATH
Set one of these environment variables before starting Neovim:
export CODEX_API_KEY="sk-..."
# or
export OPENAI_API_KEY="sk-...":GhostStatusShows:
- Active backend (opencode/codex)
- Connection state (CONNECTED/INITIALIZING/DISCONNECTED)
- Last error message (if any)
Install code quality tools:
# macOS
brew install stylua luacheck
pip install pre-commit
# Or manually:
# stylua: https://github.com/JohnnyMorganz/StyLua
# luacheck: https://github.com/mpeterv/luacheck
# pre-commit: https://pre-commit.com/# Install pre-commit hooks (runs stylua + luacheck on commit)
make precommit-install| Target | Description |
|---|---|
make format |
Format Lua files with stylua |
make format-check |
Check formatting (no changes) |
make lint |
Run luacheck linter |
make check |
Run format-check + lint |
make precommit |
Run pre-commit on all files |
Configuration files: .stylua.toml, .luacheckrc
MIT