Personal Neovim setup based on LazyVim, managed with lazy.nvim. It extends LazyVim with third-party plugins, local overrides, colorscheme persistence, and workflow commands for Ruby, SQL, JSON, and more.
For LazyVim’s built-in features and default keymaps, see the LazyVim documentation.
- Neovim ≥ 0.11.2 (LuaJIT build)
- Git ≥ 2.19.0
- A Nerd Font (icons in UI plugins)
- Optional CLI tools used by custom commands:
python3,sqlformat,underscore,ogg123(audio commands), etc.
Use install.sh — it checks dependencies, backs up any existing config, installs into ~/.config/nvim, syncs plugins, and opens Neovim.
There are three ways to install (the script picks the right one automatically):
| Situation | What ./install.sh does |
|---|---|
curl | bash |
clone — clones into ~/.config/nvim |
Clone into ~/.config/nvim, then ./install.sh |
ready — config is already in place; only syncs plugins (no backup, no symlink) |
Clone elsewhere (e.g. ~/Projects/nvim-config), then ./install.sh |
link — symlinks ~/.config/nvim → that folder |
curl -fsSL https://raw.githubusercontent.com/alexesba/nvim-config/master/install.sh | bashClones into ~/.config/nvim, syncs plugins, opens Neovim.
git clone https://github.com/alexesba/nvim-config.git ~/.config/nvim
cd ~/.config/nvim
./install.shThe repo is already where Neovim expects it. The script detects ready mode: it does not move or symlink your config, only runs plugin sync and opens Neovim.
git clone https://github.com/alexesba/nvim-config.git ~/Projects/nvim-config
cd ~/Projects/nvim-config
./install.shUses link mode: symlinks ~/.config/nvim → your clone. Good if you keep the repo under ~/Projects (or similar) and edit it there.
Rule of thumb: if you run ./install.sh from inside the repo, the script checks whether that folder is ~/.config/nvim (ready) or should be linked to it (link).
- Check for
gitand Neovim (install Neovim via Homebrew/apt/pacman/dnf if missing) - Back up existing
~/.config/nvimto~/.config/nvim.bak.<timestamp> - clone or link as above
- Ask for your
<leader>key when run interactively (default,; skipped ifleader.local.luaalready exists) - Seed
options.local.luaandkeymaps.local.luafrom examples if missing (never overwrites existing files) - Run
nvim --headless "+Lazy! sync"to install plugins - Open Neovim
./install.sh --help # usage and environment variables| Variable | Default | Purpose |
|---|---|---|
INSTALL_DIR |
~/.config/nvim |
Neovim config path |
REPO_URL |
https://github.com/alexesba/nvim-config.git |
Clone URL (clone mode) |
REPO_BRANCH |
master |
Branch to clone |
INSTALL_MODE |
auto (ready / link / clone) |
Force clone or link |
MAPLEADER |
, |
Leader key when install is non-interactive (curl | bash) |
FORCE_LEADER |
— | Set to 1 to choose leader again during install |
FORCE_LOCAL |
— | Set to 1 to re-copy options.local.lua / keymaps.local.lua from examples |
After install: :Lazy, :Lazy sync, :LazyExtras.
Clone without install.sh? Defaults work out of the box (<leader> is ,). Run nvim --headless "+Lazy! sync" +qa once, then copy any *.local.lua.example to *.local.lua to customize (those files are gitignored).
- LazyVim — IDE-style defaults (LSP, formatting, linting, treesitter, which-key, etc.)
- lazy.nvim — plugin manager
- Leader key —
<leader>(default:,comma). Override inlua/config/leader.local.lua(gitignored)
| Extra | Purpose |
|---|---|
ai.copilot |
GitHub Copilot integration |
ai.copilot-chat |
Copilot Chat |
coding.mini-surround |
Surround text with pairs (brackets, quotes, etc.) |
These are added under lua/plugins/ and are not shipped with LazyVim by default. LazyVim’s own stack (LSP, Treesitter, Snacks picker, Tokyo Night, etc.) is documented in the LazyVim docs.
| Plugin | Config file | Why it’s here |
|---|---|---|
| oil.nvim | oil.lua |
Default file explorer (Neo-tree / mini.files / Snacks explorer disabled) |
| luatab.nvim | luatab.lua |
Tab line UI (bufferline disabled) |
| markdown-preview.nvim | markdown_preview.lua |
Live Markdown preview in the browser |
| vim-dadbod + UI + completion | dadbod.lua |
SQL database connections and query buffers |
| vim-abolish | tpope.lua |
Case and variant word operations (cr* maps) |
| vim-bundler | tpope.lua |
Jump to gems from Gemfile (gf in Ruby buffers) |
| asyncrun.vim | asyncrun.lua |
Background shell jobs (used by :Reprobado / :Reprobada audio) |
| vim-fetch | vim-fetch.lua |
Preserve file cursor position across reloads |
| sonokai | sonokai.lua |
Extra colorscheme (lazy-loaded; pick via Snacks or :colorscheme) |
| clipring.nvim | clipring.lua |
Persistent yank/clipboard history ring |
- Replaces LazyVim’s default file trees as the primary explorer.
-opens the parent directory;:Explorer/:Explore/:Expopen Oil in the current directory.nvim .opens Oil when you pass a directory on the command line.
- Requires a one-time build: lazy.nvim runs
cd app && npx --yes yarnon install. - Loads only for
markdown/mdfiletypes. <leader>mptoggles the browser preview (MarkdownPreviewToggle).- Preview does not auto-start or auto-close (
mkdp_auto_start/mkdp_auto_closeare off).
:DBUIopens the database UI;:DBUIToggle,:DBUIAddConnection,:DBUIFindBufferare also available.- SQL completion loads in
sql/mysql/plsqlbuffers viavim-dadbod-completion. - Connection strings and UI layout follow vim-dadbod-ui defaults (Nerd Font icons enabled).
- vim-abolish — case and abbreviation helpers on
crs,crm,crc,cru,cr-,cr.. - vim-bundler —
gfon a gem name in a Ruby buffer jumps to the bundled gem (may overlap with LazyVim git/maps; only active inrubyfiletype).
:AsyncRunruns shell commands without blocking the editor.- Custom
:Reprobado/:Reprobadacommands play Ogg files fromlua/ogg/viaogg123. system-deps.luatries to installvorbis-toolsifogg123is missing (Homebrew / apt / pacman / dnf / zypper).
<leader>yhopens the yank history picker.- Ring is persisted across sessions (
persist = true, up to 100 entries).
- Not loaded until selected; install list includes it in
lua/config/lazy.luafor:colorscheme sonokaior the Snacks colorscheme picker.
| File | What it changes |
|---|---|
snaks.lua |
Disables Snacks file explorer (Oil is used instead); custom Snacks picker keys (<leader>fg, <leader>fk) |
noice.lua |
Rounded LSP hover borders only; cmdline/messages/popupmenu stay on Vim defaults |
lsp.lua |
Disables diagnostic virtual text (float on CursorHold in autocmds.lua) |
colorscheme-persist.lua |
Saves/restores last colorscheme to ~/.local/state/nvim/last-colorscheme |
disabled.lua |
Turns off bufferline.nvim, neo-tree.nvim, mini.files |
nvin-web-devicons.lua |
Ensures devicons are lazy-loaded (dependency for Oil, luatab) |
system-deps.lua |
Meta-spec that installs system vorbis-tools when needed (not a Neovim plugin) |
bufferline.nvimneo-tree.nvimmini.files- Snacks file explorer (Oil is used instead)
- Line numbers + relative numbers, 81-column guide, rounded floating window borders
- Arrow keys disabled in Normal / Insert / Visual (use
hjkl) - Search centering (
n/Nwithzz), betterJjoin, undo breakpoints in Insert - Diagnostics — virtual text off; float opens on
CursorHold(seelua/plugins/lsp.lua,lua/config/autocmds.lua) - Colorschemes — default Tokyo Night (moon); last pick restored on startup (
:ColorScheme,<leader>uC, or:colorscheme); fallback Tokyo Night if saved theme fails
Saved theme path: ~/.local/state/nvim/last-colorscheme
Common maps from the default Snacks picker extra:
| Key | Action |
|---|---|
<leader><space> |
Find files (project root) |
<leader>ff |
Find files (project root) |
<leader>fg |
Live grep (project root; custom — overrides LazyVim’s git-files on this key) |
<leader>sg |
Live grep (project root; LazyVim default) |
<leader>sG |
Live grep (cwd) |
<leader>fk |
Grep word under cursor / visual selection (project root) |
<leader>sw |
Same as <leader>fk (LazyVim default key) |
<leader>fb / <leader>, |
Buffers |
<leader>fc |
Find config file |
<leader>sk |
Keymaps |
<leader>sh |
Help pages |
Press <leader> and wait for which-key for the full list.
<leader>uCor:ColorScheme— pick a theme in Snacks (live preview, works on empty buffers).- Or
:colorscheme <name>(e.g.sonokai,tokyonight). - Restart Neovim — your last theme is restored automatically.
To reset persistence:
rm -f ~/.local/state/nvim/last-colorscheme| Key / command | Action |
|---|---|
- |
Open parent directory |
:Explorer, :Explore, :Exp |
Open Oil in current directory |
| Key | Action |
|---|---|
<leader>yh |
Open yank/clipboard history picker |
| Key | Action |
|---|---|
<leader>mp |
Toggle Markdown preview (markdown / md buffers) |
| Command | Action |
|---|---|
:DBUI |
Database UI |
:DBUIToggle |
Toggle UI |
:DBUIAddConnection |
Add connection |
:DBUIFindBuffer |
Find SQL buffer |
| Key | Action |
|---|---|
<leader>1 … <leader>9, <leader>0 |
Go to tab 1–9 / last tab |
| Key / command | Action |
|---|---|
<leader>l |
Lazy plugin manager (:Lazy) |
<leader>yp |
Copy full file path to clipboard |
<leader>yr |
Copy file path relative to project root (cwd fallback) |
<leader>cf |
Format (LazyVim / conform) |
<leader>fc |
Find config file (Snacks picker) |
Restart Neovim after structural config changes (lazy.nvim does not fully reload on :source). While editing Lua config, :LazyDev adds LSP and tooling for plugin development.
Formatting and cleanup: FormatJSON, FormatJSONV2, FormatCss, FormatSQL, FormatSQLV2, FormatXML, RemoveEmptyLines, RemoveExtraEmptyLines, CleanWhiteSpaces, ConvertTabToSpaces, AddLineNumbers, RemoveLineBreak
Quotes / Ruby: DoubleQuotes, SingleQuotes, DoubleQuotesC, SingleQuotesC, HashNewSyntax, HashOldSyntax, UpdateRubyHashesByLines, UnscapeDoubleQuotes
Paths: CopyFullPath, CopyRelativePath
Misc: ShowHiName (highlight group under cursor), Reprobado / Reprobada (audio; needs ogg123)
Use :command or Snacks <leader>sk to browse keymaps and discover more.
| Key | Action |
|---|---|
<leader>no / <leader>na |
Play Reprobado / Reprobada sound |
<leader>rp |
Start substitute for word under cursor |
Y |
Yank to end of line |
Esc |
Clear search highlight |
LazyVim’s own maps (LSP, windows, etc.) still apply — press <leader> and wait for which-key, or check LazyVim keymaps.
├── install.sh # Automated install + plugin sync + launch nvim
├── init.lua # Entry: loads config.lazy
├── lazyvim.json # LazyVim extras and version metadata
├── lua/
│ ├── config/
│ │ ├── lazy.lua # lazy.nvim + LazyVim bootstrap
│ │ ├── options.lua # vim options + loads leader/options .local.lua
│ │ ├── keymaps.lua # Custom keymaps + loads keymaps.local.lua
│ │ ├── leader.local.lua.example
│ │ ├── options.local.lua.example
│ │ ├── keymaps.local.lua.example
│ │ ├── autocmds.lua # Autocmds + user commands
│ │ └── colorscheme.lua # Persist/load theme helpers
│ ├── plugins/ # Plugin specs (one file per concern)
│ └── utils/
│ └── local.lua # dofile loader for gitignored *.local.lua overlays
└── README.md
Add or override plugins by creating files under lua/plugins/; they are imported automatically from lua/config/lazy.lua.
Tracked defaults live in lua/config/options.lua and lua/config/keymaps.lua. Put your machine-specific changes in gitignored *.local.lua files so git pull never conflicts with your personal prefs.
lua/utils/local.lua provides a small loader used by the config:
require("utils.local").load("options") -- dofile lua/config/options.local.lua if it exists- Looks for
lua/config/<name>.local.luaunder your Neovim config directory (stdpath("config")). - Missing files are skipped silently (no error).
- Syntax or runtime errors in a
.local.luafile show avim.notifywarning; Neovim still starts with repo defaults.
| Gitignored file | Example template | When it loads | Typical contents |
|---|---|---|---|
leader.local.lua |
leader.local.lua.example |
Early in options.lua, right after default vim.g.mapleader |
vim.g.mapleader, vim.g.maplocalleader |
options.local.lua |
options.local.lua.example |
End of options.lua, after all repo vim.opt / vim.g |
vim.opt.*, vim.g.*, plugin globals |
keymaps.local.lua |
keymaps.local.lua.example |
End of keymaps.lua, after repo keymaps |
map(...) calls via utils.map |
Leader loads before other vim.g settings in options.lua so your leader key is set early. Options and keymaps load last so your values override repo defaults.
All three paths are listed in .gitignore — they stay on your machine only.
With install.sh (recommended on first install):
- Prompts for
<leader>and writesleader.local.lua(skipped if the file already exists). - Copies
options.local.lua.example→options.local.luaandkeymaps.local.lua.example→keymaps.local.luaonly when those files are missing.
Manually (clone without install.sh, or add overlays later):
cp lua/config/leader.local.lua.example lua/config/leader.local.lua # optional; default leader is ,
cp lua/config/options.local.lua.example lua/config/options.local.lua
cp lua/config/keymaps.local.lua.example lua/config/keymaps.local.luaThen edit the .local.lua files. Restart Neovim after changes (lazy.nvim does not fully hot-reload structural config).
leader.local.lua:
vim.g.mapleader = " "
vim.g.maplocalleader = "\\"options.local.lua:
vim.opt.relativenumber = false
vim.opt.colorcolumn = "100"
vim.opt.wrap = truekeymaps.local.lua:
local map = require("utils.map").map
map("n", "<leader>x", "<cmd>echo 'my map'<cr>", { noremap = true, silent = true })install.sh never overwrites existing local files. To regenerate from examples:
| Goal | Command |
|---|---|
| Re-prompt for leader | FORCE_LEADER=1 ./install.sh |
| Re-copy options/keymaps templates | FORCE_LOCAL=1 ./install.sh |
| Both | FORCE_LEADER=1 FORCE_LOCAL=1 ./install.sh |
FORCE_LOCAL only affects options.local.lua and keymaps.local.lua; leader still uses FORCE_LEADER.
- Change default colorscheme behavior —
lua/plugins/colorscheme-persist.lua,lua/config/colorscheme.lua - Add plugins — new
lua/plugins/<name>.luareturning a lazy spec table - Toggle LazyVim extras —
:LazyExtrasor editlazyvim.json - Disable a plugin —
enabled = falsein a spec, orlua/plugins/disabled.lua