Skip to content

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

nvim

On 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, and tabby all come from nvim-web-devicons and render as boxes/garbage without one.
  • ripgrep for Telescope’s live_grep.
  • Whichever language servers you actually want, installed and on PATH yourself: 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

CommandWhat it does
nvimNormal launch.
nvim --headless -c 'qa'Quick sanity check that nothing errors on startup — useful after editing config.
:LazyOpen the plugin manager UI (status, updates, lazy-load reasons).
:Lazy syncInstall/update/clean plugins — run after adding or editing a plugins/*.lua spec.
:checkhealthDiagnose 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

KeysAction
<leader>eToggle file explorer (nvim-tree)
<leader>ffFind files (Telescope)
<leader>fgLive grep (Telescope)
<leader>fbList buffers (Telescope)
<leader>fhHelp tags (Telescope)

Git

KeysAction
<leader>gsPreview hunk under cursor (gitsigns)
<leader>gcToggle current-line git blame (gitsigns)
<leader>ggOpen the Neogit UI

LSP (buffer-local, active once a language server attaches)

KeysAction
gdGo to definition
KHover documentation
grFind references
<leader>rnRename symbol

AI — CodeCompanion (<leader>c*)

KeysAction
<leader>ccOpen AI chat
<leader>caContextual AI actions (normal or visual selection)
<leader>ceExplain code
<leader>cfFix code
<leader>ctGenerate tests

AI — Claude Code (<leader>a*)

KeysAction
<leader>acToggle Claude
<leader>afFocus Claude
<leader>arResume Claude session
<leader>aCContinue Claude session
<leader>amSelect Claude model
<leader>abAdd current buffer to Claude’s context
<leader>asAdd file to Claude (normal mode) / send selection to Claude (visual mode)
<leader>aaAccept diff
<leader>adDeny 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

KeysAction
<leader>rcConnect to a remote host
<leader>rdDisconnect
<leader>reEdit SSHFS config
<leader>rfFind files on the remote host
<leader>rgLive grep on the remote host

Tabs

KeysAction
<leader>tcClose current tab
<leader>toClose all other tabs
<leader>tlNext tab
<leader>thPrevious 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.

Last updated on