Saltar al contenido

LazyVim a fondo: instalación y estructura

La arquitectura real de LazyVim: lazy.nvim el gestor debajo, la distro como un plugin que importa specs encima. Instalación con red de seguridad, el ciclo de arranque completo, dónde viven los defaults, el sistema de Extras con lazyvim.json, y el updater con su lockfile.

El error clásico al instalar LazyVim es tratarla como un producto cerrado: algo que se instala, funciona y no se mira por dentro. Es exactamente al revés. LazyVim es la estructura que tú montaste en el Nivel 2 — un init.lua, lua/config, lua/plugins, lazy.nvim gobernando specs — con una sola pieza nueva: un plugin que, al importarse, aporta decenas de specs ya escritas. Si entiendes esa pieza, entiendes la distro entera: dónde vive cada default, por qué tu configuración gana a la suya, y qué toca exactamente el botón de actualizar. Esta lección es el plano del edificio antes de mudarte.

  • Separar las dos piezas: lazy.nvim el gestor (lección 2.2) y LazyVim la distribución montada encima.
  • Separar lo que LazyVim aporta hoy de lo que Neovim 0.12 ya trae de serie.
  • Instalar LazyVim de forma segura y verificar la instalación con :LazyHealth.
  • Recorrer el ciclo de arranque completo: qué se carga, en qué orden y desde dónde.
  • Localizar dónde viven los defaults de la distro en tu disco, para leerlos.
  • Dominar el sistema de Extras: :LazyExtras, el archivo lazyvim.json y los imports manuales.
  • Entender el updater: el checker, :Lazy update, :Lazy restore y el lockfile.

Las dos piezas: el gestor y la distro

Conviene deshacer una confusión de nombres que arrastra medio internet, porque los dos proyectos son del mismo autor y casi se llaman igual.

lazy.nvim es el gestor de plugins. Lo conoces de la lección 2.2: lee specs declarativas, instala, carga con pereza, escribe lazy-lock.json. Es una librería; no opina sobre qué plugins usas.

LazyVim es la distribución. Y aquí está la elegancia del diseño: no es un fork de Neovim, ni un programa aparte, ni siquiera un instalador. Es un plugin más de lazy.nvim — se declara como "LazyVim/LazyVim" en tu spec — con la particularidad de que al importarlo trae consigo todas las specs de la distro: sus plugins, sus opciones, sus keymaps y sus autocmds. La distro entera entra por la misma puerta que cualquier plugin tuyo, y eso significa que todas las reglas de lazy.nvim que ya conoces le aplican: sus specs se fusionan con las tuyas, su lockfile es el mismo lazy-lock.json, y su código está en tu disco donde el gestor deja todo lo demás.

Las versiones recientes de LazyVim exigen Neovim moderno y usan la configuración nativa de LSP (vim.lsp.config) por debajo de nvim-lspconfig, y la rama main reescrita de nvim-treesitter — la misma migración que tú hiciste a mano en el Nivel 2, absorbida por la distro para sus usuarios.

Qué aporta LazyVim en Neovim 0.12

Durante años, la propuesta de una distro se resumía en «te doy gestor de plugins, completado y LSP ya cableados». Neovim 0.12 (estable actual: 0.12.4) trae las tres cosas de serie, así que ese argumento se ha quedado a medias. Vale la pena separar el grano de la paja:

Argumento clásico Estado en 0.12
«Te monta el gestor de plugins» Ya no es argumento. vim.pack es nativo y trae lockfile.
«Te deja el autocompletado listo» Ya no es argumento. vim.o.autocomplete = true y vim.opt.completeopt bastan para el día a día.
«Te configura el LSP» Ya no es argumento. vim.lsp.config() y vim.lsp.enable(), más una carpeta lsp/ en el runtimepath, hacen el trabajo.
«Un conjunto de plugins curado» Sigue en pie. La base de LazyVim ronda los 34 plugins elegidos para no pisarse entre sí; ese trabajo de coordinación es real y aquí ya está hecho.
«Keymaps coherentes y documentados» Sigue en pie. Un mapa de teclas con grupos consistentes y which-key describiéndolo todo.
«Extras por lenguaje» Sigue en pie. LSP, DAP, parsers y formateo coordinados por lenguaje, con una línea.
«Alguien lo mantiene cuando algo se rompe» Sigue en pie. Cuando nvim-treesitter se reescribió por completo, la distro absorbió el golpe; una config propia no.

Lo que sí te cuesta

Dos cosas, y conviene saberlas antes de instalar. La primera: heredas su reparto de teclas, y LazyVim mapea mucho. En concreto cede a flash.nvim las teclas s y S (en Normal, Visual y operador-pendiente), r y R (solo en operador-pendiente y Visual: búsqueda remota y por nodos) y <C-Space> (selección incremental por Treesitter) — y <C-Space> es justo la tecla que este track reserva para el autocompletado. La segunda: heredas su pila. LazyVim sigue montando nvim-lspconfig y mason.nvim para los servidores, y blink.cmp para el completado. Funciona bien, pero es una capa por encima de lo que 0.12 ya sabe hacer solo. No es un defecto: es una decisión de compatibilidad. Solo tienes que saber que está ahí.

La pregunta útil no es «distro sí o no»

Es «¿qué quiero delegar?». Si lo que te pesa es mantener cuarenta plugins al día y tener soporte decente de seis lenguajes sin dedicarle tardes, LazyVim sigue siendo una compra excelente. Si lo que quieres es un editor pequeño y tuyo, 0.12 te lo pone más fácil que nunca sin distro. Lo que ya no tiene sentido es instalar LazyVim porque configurar el LSP es difícil: hoy no lo es, y tú lo sabes de primera mano.

Instalación segura

Dos vías, según lo decidido en la lección anterior. Si aún estás evaluando, usa la jaula de NVIM_APPNAME que montaste allí (git clone del starter en ~/.config/nvim-lazy y NVIM_APPNAME=nvim-lazy nvim): todo lo que sigue funciona igual dentro de ella. Si ya decidiste adoptarla como config principal, entonces con copia de seguridad completa:

Shell
# 1) Copia de seguridad de tu config, datos, estado y cachémv ~/.config/nvim ~/.config/nvim.bakmv ~/.local/share/nvim ~/.local/share/nvim.bakmv ~/.local/state/nvim ~/.local/state/nvim.bakmv ~/.cache/nvim ~/.cache/nvim.bak# 2) Clona el starter oficial de LazyVimgit clone https://github.com/LazyVim/starter ~/.config/nvim# 3) Quita el historial git del starter (para hacerlo tuyo)rm -rf ~/.config/nvim/.git# 4) Arranca: instalará todo solonvim

El primer arranque descarga e instala decenas de plugins. Cuando termine, reinicia y ejecuta :LazyHealth: es un comando de la propia distro que fuerza la carga de todos los plugins y lanza :checkhealth encima — la forma más rápida de descubrir qué binario del sistema te falta (un compilador, ripgrep, lazygit, la CLI de tree-sitter que la rama nueva exige para compilar parsers) antes de que te falte en mitad del trabajo.

El starter es tuyo desde el minuto uno

Fíjate en el paso 3: se borra el .git del starter precisamente porque ese repo no se actualiza como parte de la distro. El starter son cuatro archivos casi vacíos que te pertenecen; lo que se actualiza es el plugin LazyVim/LazyVim que esos archivos importan. Versiona tu carpeta ~/.config/nvim en tu repo de dotfiles, como hacías con tu config a mano: es la misma disciplina.

La estructura (te sonará)

Texto
~/.config/nvim/├── init.lua                  # una línea: require("config.lazy")├── lua/│   ├── config/│   │   ├── lazy.lua          # arranca lazy.nvim con la spec de LazyVim│   │   ├── options.lua       # TUS opciones (encima de las de LazyVim)│   │   ├── keymaps.lua       # TUS keymaps│   │   └── autocmds.lua      # TUS autocmds│   └── plugins/              # TUS specs: añadir, override o desactivar├── lazyvim.json              # los Extras que activas (lo escribe :LazyExtras)└── lazy-lock.json            # versiones exactas (versiónalo en Git)

Es tu misma estructura del Nivel 2, con dos reglas nuevas

lua/config para opciones, keymaps y autocmds; lua/plugins para specs. Idéntico a lo que montaste a mano. Las reglas nuevas: uno, los archivos de lua/config los carga LazyVim automáticamente en el momento correcto — no los requieras tú a mano, ni a los tuyos ni a los suyos (lazyvim.config.*), porque los cargarías dos veces. Dos, LazyVim trae sus propios options, keymaps y autocmds por defecto, que se cargan antes que los tuyos: tus archivos no parten de cero, corrigen encima.

El ciclo de arranque

Saber qué pasa entre que tecleas nvim y ves el dashboard es lo que separa usar la distro de entenderla. El orden importa porque explica quién gana cuando dos capas tocan lo mismo:

Ese orden de la spec — base, Extras, lo tuyo — no es una convención opcional: LazyVim lo comprueba al arrancar y te muestra un aviso si lo alteras, porque de él depende que tus overrides ganen. Es la misma regla de fusión de specs de lazy.nvim que viste en la lección 2.2, usada aquí como arquitectura: la distro no te protege de ella, se apoya en ella.

Dónde viven los defaults

Todo lo que la distro decide está en Lua legible, en tu disco, donde lazy.nvim instala cualquier plugin:

Texto
~/.local/share/nvim/lazy/LazyVim/lua/lazyvim/├── config/          # sus options.lua, keymaps.lua, autocmds.lua por defecto└── plugins/         # las specs de la base, un archivo por área    └── extras/      # TODOS los extras, organizados por categoría

Este directorio es tu documentación de primera mano. ¿Quieres saber exactamente cómo configura LazyVim su statusline, o qué teclas le da a un plugin? No busques un blog: abre el archivo. La regla que te acompañará las tres próximas lecciones es leer ahí, cambiar en tu lua/plugins/ — nunca editar estos archivos, porque la próxima actualización los pisará.

Un solo principio explica toda la personalización de LazyVim: lo tuyo siempre carga después. La lección 5.3 lo explota sistemáticamente.

El sistema de Extras

Los Extras son módulos oficiales opcionales que añaden una funcionalidad completa ya configurada y coordinada. Los de lenguaje son los más valiosos: activar uno trae el servidor LSP con sus banderas, el formateador, el adaptador de depuración y el parser de Treesitter, todo junto y probado. Las categorías reales, tal como aparecen en la documentación: ai, coding, dap, editor, formatting, lang, linting, lsp, test, ui y util, más un modo especial para VS Code.

Se gestionan con una UI propia:

VIM
:LazyExtras

Se abre una lista navegable con secciones: los extras activos, los recomendados para lo que hay en tu proyecto (LazyVim mira el buffer y el directorio — con un Cargo.toml a la vista te sugerirá el de Rust), y el catálogo completo. Pulsa x sobre un extra para activarlo o desactivarlo y reinicia.

¿Y dónde se apunta lo que activas? Aquí viene el detalle que casi todo el mundo descubre tarde: :LazyExtras no toca tu lua/config/lazy.lua. Escribe en un archivo propio en la raíz de tu config, lazyvim.json, donde mantiene la lista de extras activos como nombres de módulo, junto a metadatos de la propia distro:

lazyvim.json (generado por :LazyExtras)JSON
{  "extras": [    "lazyvim.plugins.extras.lang.clangd",    "lazyvim.plugins.extras.lang.rust",    "lazyvim.plugins.extras.lang.typescript"  ],  "news": { "NEWS.md": "..." },  "version": 8}

LazyVim lee ese archivo al arrancar e importa esos módulos en su sitio del ciclo — después de la base, antes de tus plugins. Consecuencia práctica: lazyvim.json es parte de tu configuración y va al repo de dotfiles igual que el lockfile; sin él, tu config en otra máquina arrancaría sin ninguno de tus lenguajes.

La vía manual sigue existiendo y es equivalente: añadir el import tú mismo en la spec de lua/config/lazy.lua, entre la base y tus plugins:

lua/config/lazy.lua (fragmento)LUA
spec = {  { "LazyVim/LazyVim", import = "lazyvim.plugins" },  -- extras añadidos a mano, si prefieres verlos en el código:  { import = "lazyvim.plugins.extras.lang.rust" },  -- tus plugins, SIEMPRE al final:  { import = "plugins" },},

Las dos vías conviven sin conflicto. La UI es más cómoda y te enseña los recomendados; el import manual deja la decisión visible en un diff de Git. Elige una como principal para no tener la lista repartida en dos sitios.

Un IDE de Rust en diez segundos, y por qué importa

Abre :LazyExtras, busca el extra de Rust en la sección de lenguajes, pulsa x, reinicia. Acabas de activar rustaceanvim con rust-analyzer afinado, crates.nvim para el Cargo.toml, el adaptador codelldb para depurar y los parsers de Treesitter, coordinados y mantenidos. Lo que en tu config a mano fue una lección entera, aquí es una tecla. Ese es el argumento que 0.12 no ha tocado: no la instalación de los plugins, sino que alguien haya decidido cuáles y cómo encajan. La lección 5.4 recorre los extras de nuestros cuatro stacks uno a uno.

El updater y el lockfile

LazyVim se actualiza con la maquinaria de lazy.nvim que ya conoces, con tres piezas encajadas que conviene distinguir:

El checker. El starter deja activado checker = { enabled = true, notify = false } en la llamada a setup: lazy.nvim comprueba periódicamente, en segundo plano, si hay actualizaciones disponibles, y lo indica discretamente en la UI de :Lazy sin interrumpirte con avisos. Comprobar no es instalar: nada cambia hasta que tú lo pidas.

La actualización. :Lazy update actualiza los plugins — la distro incluida, porque es un plugin más — y reescribe lazy-lock.json con los commits nuevos. El propio plugin de LazyVim va fijado por defecto a su última release estable, no al último commit; si quieres seguir el desarrollo, la documentación oficial muestra cómo poner version = false en su spec, con la advertencia de que eso es elegir la rama rápida. Cuando una actualización de la distro trae cambios grandes o rupturas, LazyVim te muestra las novedades (su NEWS.md) al arrancar, y <leader>L abre el changelog completo cuando quieras revisarlo.

La vuelta atrás. :Lazy restore reinstala exactamente las versiones apuntadas en lazy-lock.json. Si versionas el lockfile en Git — hazlo —, tu red de seguridad es doble: restore te devuelve al último estado bueno conocido, y el historial de Git te deja viajar a cualquier estado anterior a ese. Actualiza cuando tengas diez minutos para comprobar que todo sigue en pie, no justo antes de una entrega; con lockfile versionado, actualizar nunca es una apuesta, solo un experimento reversible.

Lo primero que haces después de instalar

Antes de escribir una sola línea de personalización, audita el teclado. LazyVim mapea mucho, y sus decisiones no tienen por qué coincidir con las tuyas:

VIM
:map s:map <C-Space>:map <Tab>:LazyHealth

En una LazyVim recién instalada verás que s y S pertenecen a flash.nvim, y que <C-Space> también (su selección incremental por Treesitter). Eso último es un problema directo en este track: <C-Space> está reservado para el autocompletado. Lo arreglamos en la lección siguiente, que es justo la de doblar la distro sin romperla.

Descubre los atajos antes de inventarte otros

Pulsa <leader> (espacio) y espera un instante: which-key te muestra el mapa completo con sus grupos — <leader>f buscar, <leader>g git, <leader>c código, <leader>x diagnósticos y listas, <leader>u interruptores de UI. Mirar ahí antes de crear un atajo te ahorra la mitad de los conflictos. Y fíjate en el patrón de los grupos: es un vocabulario diseñado, no una acumulación.

Convención sobre configuración: el precio de lo predecible

Detente en lo que ha hecho posible esta lección entera, porque es un principio de diseño con nombre propio: convención sobre configuración. LazyVim no te pregunta dónde quieres poner tus specs, ni cómo quieres estructurar tus opciones, ni en qué orden deben fusionarse las capas. Lo decide por ti — lua/plugins/ para specs, lua/config/ para lo demás, base-extras-tuyo como orden — y a cambio de renunciar a esas decisiones obtienes algo que ninguna cantidad de flexibilidad compra: que tu configuración se parezca a la de todos los demás usuarios.

Ese parecido es un activo con intereses compuestos. Es lo que hace que cualquier respuesta de foro aplique a tu caso sin adaptación. Es lo que permite que :LazyExtras exista: los extras solo pueden inyectarse limpiamente porque saben exactamente qué estructura van a encontrar. Es lo que hace que la documentación sea corta — una convención es documentación que no hay que escribir, porque en su lugar hay una expectativa compartida. Y es el mismo trato que hace Rails con sus carpetas, Cargo con src/main.rs, o cualquier linter con configuración cero: donde hay convención, el conocimiento se vuelve transferible entre proyectos y entre personas, y esa transferibilidad vale más que la libertad que costó.

El precio también hay que decirlo, porque siempre lo hay: las convenciones solo rinden mientras las conoces. Quien copia un override de LazyVim sin saber que existe un orden de imports comprobado al arranque, o que lazyvim.json guarda sus extras, vive en una casa con reglas que nadie le contó — y las reglas que no conoces no te simplifican la vida, te la vuelven mágica, que es lo mismo que frágil. Por eso esta lección ha sido un plano y no un tutorial: la convención te sirve exactamente en la medida en que podrías reconstruirla. Ese es el criterio, aquí y en cualquier framework: adopta las convenciones que entiendas, y antes de pelearte con una, entiende qué está comprando el proyecto con ella.

Monta y explora

  1. Instala LazyVim — en la jaula de NVIM_APPNAME o como config principal con copia de seguridad — y pasa :LazyHealth. Arregla lo que marque en rojo (binarios que faltan, la CLI de tree-sitter).
  2. Abre :Lazy y recorre la lista de plugins de la base. Anota tres que no conozcas y averigua qué hacen con su README.
  3. Ejecuta :map s y :map <C-Space> y anota quién los tiene.
  4. Abre :LazyExtras, identifica las secciones (activos, recomendados, catálogo) y activa el extra de TypeScript. Reinicia.
  5. Abre lazyvim.json y comprueba que el extra que activaste está apuntado ahí — y que tu lua/config/lazy.lua no ha cambiado. Añade lazyvim.json y lazy-lock.json a tu repo de dotfiles.
  6. Navega a ~/.local/share/nvim/lazy/LazyVim/lua/lazyvim/plugins/ y abre dos archivos de la base. Es la documentación primaria de las dos próximas lecciones: comprueba que puedes leerla, porque son specs como las tuyas.
  7. Mueve el import de { import = "plugins" } arriba del todo en lua/config/lazy.lua, reinicia y lee el aviso que te da LazyVim. Devuélvelo a su sitio: acabas de ver la comprobación de orden en acción.
  8. Pregúntate en voz alta qué de lo que acabas de instalar no podrías montar tú en media hora con 0.12. Esa respuesta es el valor real de la distro para ti.