Usage
Deployment
There’s no separate install step for this config specifically — it’s deployed as part of the
Dotfiles monorepo. ~/.config is a symlink to the root of that repository, so nvim/ inside it
automatically becomes ~/.config/nvim, which is where Neovim looks for its config by default.
Note
This means editing ~/.config/nvim/lua/plugins/foo.lua and editing this repo’s nvim/lua/plugins/foo.lua
are the same file.
First launch
nvimOn the very first run, lua/config/lazy.lua detects that lazy.nvim itself isn’t installed yet, clones it
into Neovim’s data directory, and then installs every plugin declared under lua/plugins/*.lua. Subsequent
launches just load already-installed plugins.
Prerequisites
- Neovim and git (for
lazy.nvim’s bootstrap clone and plugin installs). - A Nerd Font in your terminal — icons in Telescope,
nvim-tree,lualine, andtabbyall come fromnvim-web-deviconsand render as boxes/garbage without one. ripgrepfor Telescope’slive_grep.- Whichever language servers you actually want, installed and on
PATHyourself:pyright-langserver,typescript-language-server,bash-language-server(see Code Explanation for how these are wired). None of them are auto-installed — the LSP setup silently no-ops for any server whose command isn’t found, so a missing server just means no LSP for that filetype, not an error.
Everyday commands
| Command | What it does |
|---|---|
nvim | Normal launch. |
nvim --headless -c 'qa' | Quick sanity check that nothing errors on startup — useful after editing config. |
:Lazy | Open the plugin manager UI (status, updates, lazy-load reasons). |
:Lazy sync | Install/update/clean plugins — run after adding or editing a plugins/*.lua spec. |
:checkhealth | Diagnose LSP, treesitter, and provider issues. |
There’s no lint/test/build tooling — “correctness” for a config change means Neovim starts without errors,
:Lazy shows the plugin loaded and healthy, and the specific feature behaves as expected when exercised
manually.
The leader key
The leader key is never remapped from Neovim’s default, which is \. Every <leader>... keymap below is
pressed as \ followed by the listed keys (e.g. <leader>ff is \ff).
Keymaps
File explorer & search
| Keys | Action |
|---|---|
<leader>e | Toggle file explorer (nvim-tree) |
<leader>ff | Find files (Telescope) |
<leader>fg | Live grep (Telescope) |
<leader>fb | List buffers (Telescope) |
<leader>fh | Help tags (Telescope) |
Git
| Keys | Action |
|---|---|
<leader>gs | Preview hunk under cursor (gitsigns) |
<leader>gc | Toggle current-line git blame (gitsigns) |
<leader>gg | Open the Neogit UI |
LSP (buffer-local, active once a language server attaches)
| Keys | Action |
|---|---|
gd | Go to definition |
K | Hover documentation |
gr | Find references |
<leader>rn | Rename symbol |
AI — CodeCompanion (<leader>c*)
| Keys | Action |
|---|---|
<leader>cc | Open AI chat |
<leader>ca | Contextual AI actions (normal or visual selection) |
<leader>ce | Explain code |
<leader>cf | Fix code |
<leader>ct | Generate tests |
AI — Claude Code (<leader>a*)
| Keys | Action |
|---|---|
<leader>ac | Toggle Claude |
<leader>af | Focus Claude |
<leader>ar | Resume Claude session |
<leader>aC | Continue Claude session |
<leader>am | Select Claude model |
<leader>ab | Add current buffer to Claude’s context |
<leader>as | Add file to Claude (normal mode) / send selection to Claude (visual mode) |
<leader>aa | Accept diff |
<leader>ad | Deny diff |
Note
claudecode.nvim and codecompanion.nvim are two independent AI assistant plugins installed side by
side, not aliases of each other — see FAQ for why.
Remote SSHFS
| Keys | Action |
|---|---|
<leader>rc | Connect to a remote host |
<leader>rd | Disconnect |
<leader>re | Edit SSHFS config |
<leader>rf | Find files on the remote host |
<leader>rg | Live grep on the remote host |
Tabs
| Keys | Action |
|---|---|
<leader>tc | Close current tab |
<leader>to | Close all other tabs |
<leader>tl | Next tab |
<leader>th | Previous tab |
Format on save
Every buffer is formatted via vim.lsp.buf.format() on BufWritePre, using whichever attached LSP client
supports textDocument/formatting, with a 200ms timeout. There’s no separate formatter plugin — formatting
quality depends entirely on the language server attached to that buffer.