A persistent Neovim AI assistant with multi-conversation support, built on OpenAI's Agents SDK.
- Persistent Conversations: Conversations survive Neovim restarts via SQLite storage
- Multi-Layout Support: Toggle between replace, pane, and tab layouts
- Streaming Output: Real-time LLM responses with animated text rendering
- Prompt History: Cycle through previous prompts with
<C-p>and<C-n> - Context Awareness: Automatic inclusion of selected code and
@filereferences - Conversation Browser: Browse and load previous conversations with
:Anya history - Intelligent Code Tools: File editing, searching, and execution with confirmation flow
- OpenRouter & Custom Providers: Drop-in support for any OpenAI-compatible API
- MCP Tools: Optional external tool access via Model Context Protocol
- Neovim 0.10+
- Python 3.11+
- An OpenAI API key (or compatible provider key)
These are not required, but enhance the experience:
| Plugin | Purpose |
|---|---|
| blink.cmp | Autocompletion for @file references and /commands in the prompt buffer |
| snacks.nvim | Powers the :Anya history conversation picker |
| img-clip.nvim | Enables image-aware paste in the prompt buffer via <C-v> and <localleader>v |
{
"igorgue/anya",
config = function()
require("anya").setup({
start_in_insert = true, -- Enter insert mode when opening the prompt
})
end,
}Plug 'igorgue/anya'Then install Python dependencies manually:
cd ~/.local/share/nvim/plugged/anya # or wherever vim-plug installs itAfter installing, register the remote plugin once:
:UpdateRemotePlugins
Then restart Neovim.
Set these before launching Neovim (e.g. in your shell profile):
| Variable | Default | Purpose |
|---|---|---|
ANYA_MODEL |
gpt-4.1 |
Model to use |
ANYA_API_KEY |
— | Override API key (e.g. for OpenRouter) |
ANYA_API_BASE |
— | Custom API base URL |
ANYA_API_TYPE |
responses |
API type: responses or chat_completions or anthropic |
ANYA_THINKING_BUDGET |
— | Reasoning effort hint for supported models |
ANYA_DISABLE_MCP |
0 |
Set to 1 to disable MCP tools |
export ANYA_API_TYPE=chat_completions
export ANYA_API_KEY="sk-or-..."
export ANYA_MODEL="anthropic/claude-opus-4-6"Any model name containing / or : is automatically routed through
https://openrouter.ai/api/v1. You can also point ANYA_API_BASE at any
other OpenAI-compatible endpoint.
require("anya").setup({
start_in_insert = true, -- Auto-enter insert mode when prompt opens (default: false)
image_clip = {
default = {
dir_path = "images",
prompt_for_file_name = false,
},
},
})Anya's daemon always runs under its own bundled Python venv (<plugin-root>/.venv),
regardless of what the shell environment looks like. This means it works correctly even
when you open Neovim from a project directory with a virtualenv activated (mise, pyenv,
conda, plain source .venv/bin/activate, etc.).
However, Neovim's rplugin host (the process that loads plugin.py) is controlled
separately by python3_host_prog. If you don't pin this, Neovim may pick up the active
project Python at startup, which won't have pynvim or the anya package installed, causing
a load failure.
Recommended fix: pin python3_host_prog to Anya's venv Python in your Neovim config:
-- in init.lua (set this before any plugin manager setup)
vim.g.python3_host_prog = vim.fn.expand("~/Code/anya/.venv/bin/python")
-- adjust the path to wherever you cloned/installed anyaWith lazy.nvim you can also set it per-plugin installation path:
vim.g.python3_host_prog = vim.fn.stdpath("data") .. "/lazy/anya/.venv/bin/python"If the daemon still fails to start, Anya will print the Python path it tried to use in the error message so you can diagnose the mismatch quickly.
⚠️ Upgrading your system Python (e.g. via mise/pyenv) will break the rplugin host unless you've pinnedpython3_host_prog. The new interpreter typically has onlypynviminstalled, so importinganya.pluginfails onhashids(or another dep),:UpdateRemotePluginssilently registers zero plugins, and:Anyastays stuck on the "Anya is loading..." stub. Either pinpython3_host_progto Anya's.venv(preferred), or install anya's deps into the new system Python straight frompyproject.toml:# from the anya repo root uv pip install --python "$(which python3)" -r pyproject.tomlAfter fixing the host, re-run
:UpdateRemotePluginsand restart Neovim.
For quick access from the terminal, add this alias to your ~/.zshrc or ~/.bashrc:
alias anya="nvim +Anya"alias anya="nvim -u ~~/.local/share/nvim/lazy/anya/standalone/init.lua +Anya"Then reload your shell:
source ~/.zshrc # or source ~/.bashrcNow you can open Anya directly by typing anya in your terminal.
| Command | Description |
|---|---|
:Anya |
Toggle Anya UI (reopens last layout) |
:Anya open |
Open Anya UI |
:Anya close |
Close Anya UI |
:Anya tab |
Open in a new tab |
:Anya pane [right|left] |
Open as a side pane |
:Anya send <text> |
Send a message without opening the UI |
:Anya cancel |
Cancel the current in-progress response |
:Anya history |
Open the conversation history picker |
:Anya daemon start |
Start the background daemon manually |
:Anya daemon stop |
Stop the background daemon |
:Anya daemon status |
Show daemon status |
:Anya help |
Show help text |
:Anya do "instruction |
Run an arbitrary command (e.g. :Anya do "write a commit for me") |
The daemon starts automatically when Neovim loads the plugin — you normally don't need to manage it manually.
- Run
:Anyato open the chat interface - Type your message in the prompt window at the bottom
- Press
<CR>to send
| Key | Mode | Action |
|---|---|---|
<CR> |
Normal / Insert | Send message |
<C-p> |
Normal / Insert | Previous prompt in history |
<C-n> |
Normal / Insert | Next prompt in history |
<C-j> |
Normal / Insert | Insert blank line |
<C-k> |
Normal / Insert | Focus chat window |
<Tab> |
Normal / Insert | Toggle focus to chat window |
<C-Up> / <C-Down> |
Normal / Insert | Increase / decrease prompt height |
<C-Left> / <C-Right> |
Normal / Insert | Resize side pane (pane layout) |
<C-a> / <C-e> |
Normal / Insert | Jump to start / end of line |
<C-u> |
Normal / Insert | Delete whole line |
<C-v> |
Normal / Insert | Smart paste: paste image via img-clip.nvim when the clipboard holds an image, otherwise do a normal paste |
<localleader>v |
Normal / Insert | Force image paste via img-clip.nvim |
| Key | Mode | Action |
|---|---|---|
<CR> |
Normal | Open code block / tool output, or toggle fold |
<Space> |
Normal | Open code block or tool output |
<Tab> |
Normal / Insert | Toggle focus to prompt window |
<C-c> |
Normal | Cancel current response |
]] / [[ |
Normal | Jump to next / previous message header |
<localleader>h |
Normal | Open conversation history |
<C-j> |
Normal | Focus prompt window |
In either buffer you can use:
@path/to/file— include a file's contents in your message/command— run a built-in slash command (e.g./review,/plan)
Both are highlighted automatically.
Conversations are saved to ~/.local/share/anya/conversations.db.
Use :Anya history to browse and reload previous conversations.
This requires snacks.nvim.
Daemon not starting?
# Start manually in the foreground to see errors
python -m anya.server.main --foregroundPlugin not loading after install?
Make sure you ran :UpdateRemotePlugins and restarted Neovim.
Streaming issues or errors?
Check the log:
tail -f ~/.local/share/anya/daemon.logCommands not found?
Confirm the Python dependencies are installed in the same environment Neovim
uses. Run :checkhealth provider to verify.
See AGENTS.md for a full technical reference covering the agent system, daemon design, IPC protocol, marker format, and tool extensibility.
TBD
If you install img-clip.nvim, Anya's prompt buffer can paste clipboard images directly into the prompt. <C-v> is image-aware and falls back to normal clipboard paste when there is no image in the clipboard. <localleader>v always tries an image paste. Anya explicitly disables img-clip.nvim drag-and-drop paste interception so terminal paste paths like <C-S-v> keep their normal behavior. The standalone config vendors img-clip.nvim the same way as the other bundled plugins.