Vikix has two editors, Neovim and Emacs, each with a config ready to use, the language servers for the languages you added, and AI: a chat on the model Super+i uses, and your agent (the one Super+a starts) beside your code. Neither is installed until you ask for it:
vikix add neovim # or: vikix add emacs; the developer bundle brings both vikix remove emacs # takes it away again; your files stay
essentials brings Emacs; developer and everything bring both. $EDITOR is nvim unless you set another.
v FILENeovim, in this terminal
Super+xAn Emacs window
e FILEThe file in a new Emacs window (the terminal waits until you close it)
eg FILEThe same, with the terminal free at once
ec FILEEmacs inside this terminal
eqEmacs with no config at all: for finding out whether the config is the problem
emacs-restartA fresh Emacs, after you changed its config (it refuses while a file is unsaved, and asks before ending open chats)
Emacs runs as a server from the moment you log in, so Super+x and e open a window at once. The first time Emacs starts on a new machine, it downloads its packages in the background: give it a few minutes before the first e.
Neovim’s config is Vikix’s own, split in two like the desktop’s:
~/.local/share/vikix/nvimWhose: Vikix’s
What: AstroNvim and Vikix’s plugins. A link into ~/vikix: vikix update keeps it current, so don’t edit it
~/.config/nvimWhose: yours
What: init.lua (your settings go at its end), your plugins in lua/plugins/, and lazy-lock.json, the plugins’ versions
Emacs’s config is a separate repository, the author’s own (emacs-void):
~/.emacs.dWhose: a git clone
What: The config, config.org. vikix update pulls it; a change of yours there can stop the pull (the update says so and carries on)
~/.local/share/vikix/emacsWhose: Vikix’s
What: vikix-ai.el, the AI setup, vikix-theme.el, which makes Emacs follow vikix theme, vikix-notes.el, your Org notes in ~/Dropbox/notes under C-c n (the agenda, the journal, org-roam’s links and graph), and vikix-python.el, Python as an IDE under C-c p (below). A link into ~/vikix, kept current by vikix update; the config loads them when they’re there
Both are in Where everything is, with the rest of your files.
Neovim is AstroNvim with a few choices of Vikix’s: Typst with a live preview (:TypstPreview), a function’s parameters shown while you type its call, jk or jj to leave insert mode, and the AI keys below. Space is the leader: press it and wait, and a menu shows what comes next.
Your own plugins go in ~/.config/nvim/lua/plugins/, one or more files that each return plugin specs. They load after Vikix’s, so yours win. example.lua there shows a plugin more, an AstroNvim setting, one of Vikix’s plugins switched off, and another colour scheme. Plain settings (vim.opt.…) and keys (vim.keymap.set(…)) can go at the end of ~/.config/nvim/init.lua, after the line that loads Vikix’s part.
The plugins are installed at the versions Vikix tested, and vikix update moves them on when Vikix tests newer ones. Plugins you add keep their own versions. After a :Lazy update of yours, Vikix’s plugins keep your versions too: updates leave them alone and say once how to take Vikix’s again.
Emacs’s config is organised in ~/.emacs.d/config.org, one section per concern (completion, Org, Lisp, languages, tools), and each section explains itself. Emacs reads it at start. SLIME in it talks to the running window manager on port 4004 (see How it fits together).
To change it, edit config.org and run emacs-restart. vikix update brings Vikix’s new AI setup into an Emacs that’s running, with your chats left open; an Emacs started without it (before Vikix 0.59) is told to restart, and vikix doctor says which you have. The clone is yours to change, but a change there can stop vikix update from pulling the author’s newer version: keep your changes in a commit of your own, or in a config of your own (below).
With vikix add python and vikix add emacs, a .py file opens as an IDE: the mode line says Py[.venv], and everything started from the file uses that venv. The venv is found by itself: the nearest .venv up from the file (the one uv venv makes in a project); for a loose script or the examples, ~/dev/python/.venv, the shared one JupyterLab runs on (Py[dev]); and for a project that declares its dependencies (pyproject.toml, requirements.txt) but has no .venv yet, none (Py[no venv]), since its packages aren’t in the shared venv: C-c p v offers to make its own. The language server (pyright, through eglot) sees the venv’s packages, the REPL is the venv’s ipython (its python when ipython isn’t in it), ruff’s findings are shown beside pyright’s as you type, and the buffer is formatted with ruff when you save it.
C-c p tTest the function at point: pytest FILE::name
C-c p TTest this file
C-c p PTest the project
C-c p rRun this file
C-c p sThe REPL, from the venv
C-c p fFormat the buffer with ruff
C-c p FFormat on save: on or off, for this buffer (on to begin with)
C-c p cruff check the project
C-c p vWhich venv this buffer uses; none, offers uv venv
C-c p iThe IDE: code left, the REPL top right, the tests’ output below it
C-c p dThe offline Python docs, in the browser
C-c p qClose the project: its files (a changed one is asked about), the REPL, the tests’ window and pyright; then the frame, so a terminal’s e FILE gets its prompt back
Tests and runs go to a compilation buffer, where a failing line is a link: Enter on it opens the file there, M-g M-n goes to the next. A key for something that isn’t installed says what to do (uv pip install pytest in the project, say) instead of failing. Nothing of this changes your own python.el or eglot settings: the venv is given to each buffer, so two projects open at once each keep theirs. C-c p F turns formatting on save off for a buffer; (setq vikix-python-format-on-save nil) in your config turns it off everywhere. A debugger isn’t part of it yet.
Say a project of yours at ~/src/pub: a pyproject.toml that lists its packages, a uv.lock, pub.py and tests/test_pub.py, and no venv yet.
e ~/src/pub/pub.py. The mode line says Py[no venv]: the project declares its packages but has no .venv, so the shared venv is not used. pyright starts on the system Python meanwhile and marks the project’s imports as unresolved: that is the sign to make the venv.
C-c p v, then y. uv makes .venv in the project, fetching the Python the pyproject asks for if it isn’t on the machine. Then, in a terminal in the folder, bring the packages and pytest in:
uv sync uv pip install pytest
Reopen the file (C-x C-v Enter). The mode line reads Py[.venv], and pyright sees the packages. For the ipython prompt, uv pip install ipython the same way; plain python -i otherwise.
C-c p i. The code stays left, the REPL opens top right, and the tests’ window waits below it. In the REPL the project is importable as it is: from pub import load, since it starts in the project’s folder. C-c C-c sends the buffer to it, as always in Emacs.
ruff format, and ruff’s findings (an unused import, a name that isn’t defined) are underlined beside pyright’s. Put point inside a test in tests/test_pub.py and press C-c p t: the window below runs pytest on that one function, by its class when it has one. A failure’s tests/test_pub.py:36: line is a link; Enter on it goes there. C-c p T runs the file, C-c p P the whole suite.
C-c p c runs ruff check over the project in the same window, a clickable line per finding. C-c p r runs the file as a script. Then magit (C-x g) as usual.
C-c p d opens the offline Python docs in the browser.
C-c p q. A changed file is asked about, then the project’s buffers, the REPL and pyright go, and the frame closes, so the terminal that ran e gets its prompt back. Files of another project in the same Emacs stay.
Two projects open at once each keep their own venv, so you can read one while the other’s REPL runs. A file that shouldn’t be reformatted gets C-c p F once.
A language server is what lets the editor complete names, jump to a definition and underline mistakes as you type. Each comes with its language, so vikix add c brings C’s, and both editors find them on PATH:
Server: ccls, clangd
Comes with: vikix add c
Server: gopls
Comes with: vikix add go
Server: rust-analyzer
Comes with: vikix add rust
Server: zls
Comes with: vikix add zig
Server: lua-language-server
Comes with: vikix add lua
Server: typescript-language-server
Comes with: either editor (npm, in ~/.local/bin)
Server: pyright
Comes with: either editor (npm)
Server: bash-language-server
Comes with: either editor (npm)
Server: ocaml-lsp-server
Comes with: opam install ocaml-lsp-server, after vikix add ocaml
Neovim also gets efm-langserver, which runs linters and formatters. In Emacs, eglot starts the server when you open a C, C++, JavaScript, TypeScript, Python, Zig or Odin file.
Both editors do the same four things, each on the settings you already made for the desktop:
Neovim: Space A c
Emacs: C-c g
Neovim: Space A q
Emacs: C-c g with a selection, or C-c G (gptel’s menu)
Neovim: Space A g
Emacs: C-c a
Neovim: Space A t
Emacs: C-c A
The chat follows vikix ai use: local for a model on this laptop (vikix ai setup first), or claude for Claude (with your key: vikix ai key set anthropic). A model set with model= in ~/.config/vikix/ai is used here too. Emacs reads that file again at each C-c g, so a change reaches an Emacs that’s already open; a model you pick in gptel’s menu stays until the file changes. On a laptop’s CPU a local model can take minutes to begin answering, because it first reads the chat’s instructions (Neovim’s are long); Claude answers in seconds.
Your agent is the one Super+a starts (Claude Code unless you chose another: vikix agent --default NAME). The editors start it the same way, with vikix agent: it gets the guide to Vikix, no API keys or SSH agent (the editors have them, the agent doesn’t need them), and a snapshot first, so vikix changes shows what it did and vikix undo takes it back. It signs in with its own login, the one it uses in a terminal. In a chat it talks over ACP (the Agent Client Protocol): Claude Code, Codex, Gemini CLI and OpenCode speak it, and vikix agent --install NAME adds one with what it needs (running it again for an agent you have adds only what’s missing). Aider and Antigravity CLI don’t: their place is the terminal key.
In Emacs, each agent chat’s transcript is kept in ~/.local/state/vikix/agent-shell/, one file per chat, named after the project, in a folder only you can read; not in the project, where agent-shell would put it. Screenshots and images you give the agent do go in the project’s .agent-shell/, which agent-shell keeps out of git.
C-c a goes back to the chat this project already has; in a folder without one it asks first (New shell starts one here), and C-u C-c a always starts another. In Neovim, a chat’s top line says who answers before you type.
Nothing starts or connects until you press a key. When something’s missing (a key, the local model, the agent or its adapter), the key says what to type, and does nothing else. Working with AI has the rest: keys, local models, and choosing an agent.
To use your own config for either editor, install Vikix with VIKIX_NVIM_REPO= or VIKIX_EMACS_REPO= set to your repository, or put yours in the folder yourself: a git clone at ~/.config/nvim or ~/.emacs.d is pulled by updates, and any other folder of yours is left alone.
In a Neovim config of your own, Vikix’s plugins aren’t there. In an Emacs config of your own, the AI setup can still be: load it after your gptel setup,
(load (expand-file-name "~/.local/share/vikix/emacs/vikix-ai") t t)
and bind vikix-ai-agent and vikix-ai-agent-terminal to keys of yours. On a machine without Vikix the file isn’t there, and the line does nothing.
~/.local/state/vikix/logs/nvim-plugins.log. :Lazy shows each plugin, and :checkhealth what’s missing.
eq. If Emacs is fine without its config, the config is the problem: the errors are in *Messages* (C-h e). After a fix, emacs-restart.
command -v gopls); the language’s feature brings it (vikix add go).
vikix doctor checks the rest, and When something breaks has more.