# Neovim Migration Checklist Source of truth for the step-by-step rebuild. Keep this concise and up to date. See details in `neovim-migration-guide.md`. ## Phase 0 — Ground Rules - [x] Create AGENTS.md with rules ## Phase 1 — Clean & Archive Legacy Config ## Phase 1.1 — Confirm scope and priorities - [x] Confirm scope and priorities for this phase ## Phase 1.2 — Inventory legacy files - [x] Inventory existing Vimscript, plugin files, and directories ## Phase 1.3 — Create archive location - [x] Create `legacy/` archive folder within this config ## Phase 1.4 — Move legacy files into archive - [x] Move legacy init files and plugin directories into `legacy/` (do not delete) ## Phase 1.5 — Document archived contents - [x] Optionally add `legacy/README.md` noting what was archived ## Phase 1.6 — Preserve selected directories - [x] Keep `undodir`, `spell`, `view`, `UltiSnips`, `templates` as-is for now (review later) ## Phase 2 — Bootstrap ## Phase 2.1 — Confirm scope and priorities - [x] Confirm scope and priorities for this phase ## Phase 2.2 — Scaffold Lua config skeleton - [x] Scaffold Lua config skeleton (`init.lua`, `lua/settings.lua`, `lua/keymaps.lua`, `lua/autocmds.lua`, `lua/utils.lua`, `lua/plugins/`) ## Phase 2.3 — Bootstrap lazy.nvim - [x] Bootstrap `lazy.nvim` plugin manager ## Phase 2.4 — Disable unused providers - [x] Disable unused providers (ruby, perl, node) ## Phase 2.5 — Ensure lazy boots without specs - [x] Ensure lazy boots without specs (add empty `lua/plugins/init.lua`) ## Phase 3 — Core Editing & LSP ## Phase 3.1 — Confirm scope and priorities - [x] Confirm scope and priorities for this phase - [x] Decision: PHP LSP = `intelephense` - [x] Decision: Enable Markdown LSP = `marksman` - [x] Decision: Use legacy `listchars` and `showbreak` values - [x] Decision: Support per‑project config for `intelephense.includePaths` - [x] Decision: No direnv fallback for local config ## Phase 3.2 — Non-plugin settings to Lua - [x] Port non-plugin settings to Lua (options, listchars, showbreak, spelllang=en_gb) ## Phase 3.3 — Core completion stack - [x] Add core completion stack: `nvim-cmp`, `cmp-nvim-lsp`, `cmp-buffer`, `cmp-path`, `LuaSnip` ## Phase 3.4 — Project‑local configuration (native exrc) - [x] Confirm scope and priorities for this subphase - [x] Decision: Use native `exrc` + `secure` instead of neoconf (neoconf incompatible with Neovim 0.11+ vim.lsp.config API) - [x] Enable `exrc` and `secure` in settings.lua - [x] Implement `.nvim.lua` loader in LSP config using `on_new_config` hook - [x] Wire `intelephense.environment.includePaths` via `.nvim.lua` - [x] Create validation workspaces: `WORKSPACE_TEST/` and `EXTERNAL_TEST/` with sample PHP files - [x] Migrate to `vim.lsp.config()` and `vim.lsp.enable()` (Neovim 0.11+ native API) - [x] Verify project settings load correctly from actual root_dir - [x] Clean up debug notifications and temporary code ## Phase 3.7 — Clean LSP config - [x] Remove debug/helper logic from LSP config - [x] Migrate from deprecated `require('lspconfig')[server].setup()` to `vim.lsp.config()` + `vim.lsp.enable()` - [x] Use `on_new_config` hook for project-local settings loading (loads from actual root_dir, not cwd) ## Phase 3.8 — Validate project-local LSP settings - [x] Create test workspaces with `.nvim.lua` files - [x] Validate settings load from actual root_dir via `on_new_config` hook - [x] Verify `gd` works for external library references via `intelephense.environment.includePaths` - [x] Clean up debug code and notifications ## Phase 3.9 — Native exrc + vim.lsp.config migration (RESOLVED) - [x] Discovered neoconf incompatible with Neovim 0.11+ (GitHub issue #116, unresolved since May 2024) - [x] Migrated to native `exrc` + `secure` approach (zero dependencies, aligned with minimal philosophy) - [x] Implemented `.nvim.lua` loader using `on_new_config` hook (loads from actual root_dir) - [x] Migrated from deprecated `require('lspconfig')` framework to `vim.lsp.config()` + `vim.lsp.enable()` - [x] Root detection handled by nvim-lspconfig's native configs (no custom root_dir needed) - [x] Validated `gd` works for external library symbols via `intelephense.environment.includePaths` - [x] Settings schema: `.nvim.lua` returns `{ lsp = { [server_name] = { settings = {...} } } }` - [x] Security: `secure` mode prompts user to trust `.nvim.lua` files before execution - [x] Kept `single_file_support = false` for `intelephense` - [x] Fixed duplicate `gd` results issue ## Phase 3.5 — LSP minimal defaults - [x] Add `nvim-lspconfig` with minimal defaults (no over-configuration) - [x] Add minimal LSP on-attach keymaps (gd, gr, K, gD, gI) - [x] Add global LSP keymaps with fallback in `lua/keymaps.lua` - [x] Intelephense: set `single_file_support=false`, root detection via nvim-lspconfig defaults - [x] Project settings loaded via `on_new_config` hook from `.nvim.lua` files ## Phase 3.6 — LSP server management (Mason) - [x] Confirm scope and priorities for this subphase - [x] Add `williamboman/mason.nvim` and `williamboman/mason-lspconfig.nvim` - [x] Ensure servers installed: `lua_ls`, `tsserver`, `html`, `cssls`, `jsonls`, `bashls`, `marksman`, `intelephense` - [x] Keep our custom per-server setup; use Mason only for installation ## Phase 4 — Navigation ## Phase 4.1 — Confirm scope and priorities - [x] Confirm scope and priorities for this phase - [x] Decision: Skip Neo-tree in favor of netrw for navigation/visual context - [x] Decision: Use netrw for project structure visualization and file preview - [x] Decision: Telescope as primary "find file" tool - [x] Decision: Add Oil.nvim for file manipulation (handles buffer sync on rename/move/delete) - [x] Note: Oil.nvim is for evaluation; alternative is mini.files if too heavy ## Phase 4.2 — Configure netrw - [x] Configure netrw with tree view, preview split, and basic settings (no banner, sensible defaults) - [x] Created `lua/netrw-config.lua` with settings: tree view, horizontal preview split below, 50/50 split, human-readable sizes - [x] Add netrw keymaps: `te` (new tab at current file's directory), `tE` (new tab at project root) - [x] Decision: No `e` or `v` keymaps - use `:Ex`, `:Vex` directly when needed - [x] Preview behavior: Enter opens file in netrw window, `p` opens 50/50 horizontal split below ## Phase 4.2.1 — PHP gf enhancement - [x] Add PHP `includeexpr` for intelligent `gf` behavior (handles `__DIR__`, `__FILE__`, `dirname(__FILE__)` patterns) - [x] Created `after/ftplugin/php.lua` with path resolution for WordPress/PHP patterns - [x] Tested and validated with test-gf.php ## Phase 4.3 — Telescope setup - [x] Add `telescope.nvim` + `telescope-fzf-native.nvim` for fuzzy finding - [x] Configure basic pickers: `find_files`, `live_grep`, `buffers`, `help_tags`, `oldfiles`, `current_buffer_fuzzy_find` - [x] Add LSP pickers: `lsp_document_symbols`, `lsp_workspace_symbols` - [x] Keymaps configured: - `ff` - Find files - `fg` - Live grep (search text) - `fb` - Find buffers (with `` to delete) - `fh` - Find help - `fr` - Recent files - `/` - Search current buffer - `fs` - Document symbols (LSP) - `fS` - Workspace symbols (LSP) - [x] Minimal UI: dropdown theme for files/buffers, no previewer for quick selection ## Phase 4.4 — Oil.nvim for file manipulation - [x] Add `stevearc/oil.nvim` for filesystem operations (rename, create, delete, copy, move) - [x] Configure to handle buffer name sync on file operations - [x] Keep minimal - use only when shell operations would cause buffer issues - [x] Keymaps configured: - `fo` - Open Oil file browser (regular buffer) - `fO` - Open Oil in floating window (with floating previews) - `` in Oil - Preview files (vertical split to right for regular, floating window for float mode) - [x] Preview splits open to the right via `vertical = true` and `split = 'belowright'` - [x] Floating window preview direction: `preview_split = "right"` - [x] Note: Evaluate practicality; can switch to `mini.files` if preferred ## Phase 5 — Treesitter ## Phase 5.1 — Confirm scope and priorities - [x] Confirm scope and priorities for this phase - [x] Decision: Focus on languages: PHP, HTML, JavaScript, TypeScript, CSS, Markdown, Lua, Bash, JSON - [x] Decision: Enable syntax highlighting and incremental selection (CR to expand, BS to shrink) - [x] Decision: Enable textobjects for functions, classes, parameters, conditionals, loops - [x] Decision: Enable autotag for HTML/PHP/JS/React files - [x] Decision: Disable indent (experimental) to start; can enable per-filetype if stable ## Phase 5.2 — Base Treesitter - [x] Add `nvim-treesitter` with incremental selection, highlighting - [x] Configure parsers: lua, vim, vimdoc, php, html, javascript, typescript, tsx, css, scss, json, markdown, markdown_inline, bash, regex - [x] Enable auto-install for missing parsers - [x] Incremental selection keymaps: CR (init/expand), S-CR (scope expand), BS (shrink) - [x] Disable for large files (>100KB) to maintain performance ## Phase 5.3 — Treesitter textobjects - [x] Add `nvim-treesitter-textobjects` - [x] Select keymaps: `af`/`if` (function), `ac`/`ic` (class), `aa`/`ia` (parameter), `ai`/`ii` (conditional), `al`/`il` (loop), `a/` (comment) - [x] Move keymaps: `]f`/`[f` (next/prev function start), `]F`/`[F` (function end), similar for classes and parameters - [x] Swap keymaps: `a`/`A` (swap parameter with next/prev) ## Phase 5.4 — Treesitter autotag - [x] Add `nvim-ts-autotag` - [x] Enable auto-close, auto-rename, and close-on-slash for HTML/PHP/JS/React/TS/Vue files ## Phase 6 — UX / Editing ## Phase 6.1 — Confirm scope and priorities - [x] Confirm scope and priorities for this phase - [x] Decision: No cursorcolumn (as per AGENTS.md) - [x] Decision: No auto-window toggling behavior (keep settings static) - [x] Decision: No motion plugin (skip leap/flash) - [x] Decision: Move undotree to separate Phase 6.8 - [x] UX settings to add: signcolumn, cursorline, colorcolumn ## Phase 6.2 — Core UX settings - [x] Add signcolumn=yes (always show gutter for LSP/git) - [x] Add cursorline (highlight current line) - [x] Add colorcolumn=80,120 (visual guides) - [x] No cursorcolumn (excluded as per AGENTS.md) - [x] No per-window autocommands (keep simple) ## Phase 6.3 — Comment.nvim - [x] Add `numToStr/Comment.nvim` - [x] Configure for gcc/gc commenting - [x] Add keymaps if needed ## Phase 6.4 — Surround - [x] Add `kylechui/nvim-surround` - [x] Minimal config with default keymaps (ys, ds, cs) ## Phase 6.5 — Autopairs - [x] Add `windwp/nvim-autopairs` - [x] Integrate with nvim-cmp ## Phase 6.6 — Indent guides - [x] Add `lukas-reineke/indent-blankline.nvim` - [x] Configure scope highlighting ## Phase 6.7 — Folding (UFO) - [x] Add `kevinhwang91/nvim-ufo` for folding - [x] Configure with Treesitter and LSP providers - [x] Add fold keymaps (za, zR, zM, etc.) ## Phase 6.8 — Undotree - [x] Add `mbbill/undotree` - [x] Add keymap to toggle undotree - [x] Configure minimal settings ## Phase 7 — Git Integration ## Phase 7.1 — Confirm scope and priorities - [x] Confirm scope and priorities for this phase - [x] Decision: Gitsigns with minimal config - signs in gutter, hunk navigation/actions only - [x] Decision: Skip markdown rendering plugins entirely ## Phase 7.2 — Gitsigns - [x] Add `lewis6991/gitsigns.nvim` - [x] Configure signs in gutter (add, change, delete, topdelete, changedelete) - [x] Add hunk navigation keymaps (]h/[h for next/prev hunk) - [x] Add hunk action keymaps (stage, reset, preview) - [x] Keep minimal - no inline blame, no advanced features ## Phase 8 — Copilot ## Phase 8.1 — Confirm scope and priorities - [x] Confirm scope and priorities for this phase - [x] Decision: Integrate Copilot into nvim-cmp as completion source - [x] Decision: Auto-trigger suggestions as you type - [x] Decision: No specific Copilot keymaps needed (use existing cmp keymaps) - [x] Decision: Enable for all filetypes - [x] Decision: Copilot suggestions appear before LSP suggestions in completion menu - [x] Node.js v22.21.1 upgraded and confirmed working ## Phase 8.2 — Copilot setup - [x] Add `zbirenbaum/copilot.lua` + `zbirenbaum/copilot-cmp` - [x] Configure copilot.lua with auto-trigger and all filetypes - [x] Add copilot-cmp as source to nvim-cmp - [x] Set copilot-cmp priority higher than LSP in completion menu - [x] Note: Copilot initializes on first InsertEnter; enter/exit insert mode once before using `:Copilot auth` ## Phase 9 — Formatting & Linting ## Phase 9.1 — Confirm scope and priorities - [x] Confirm scope and priorities for this phase - [x] Decision: Formatters - prettier (JS/TS/CSS/JSON/MD/HTML), phpcbf (PHP), stylua (Lua), black (Python) - [x] Decision: Linters - eslint (JS/TS), phpcs (PHP), markdownlint (Markdown), ruff (Python) - [x] Decision: Project-local executables preferred, fallback to global (node_modules/.bin/, vendor/bin/) - [x] Decision: phpcs/phpcbf already installed globally with WordPress coding standards - no installation needed - [x] Decision: Format-on-save enabled by default with toggle capability - [x] Decision: Manual format keymaps: `lf` (normal), `lf` (visual range) - [x] Decision: Respect project config files (.prettierrc, phpcs.xml, .eslintrc, pyproject.toml, etc.) - [x] Strategy: Helper function detects project-local executables first, then global - [x] WordPress: phpcs.xml in project root or --standard=WordPress flag for WordPress projects - [x] Philosophy: Formatters are authoritative source of truth; Neovim settings should match formatter rules per filetype - [x] Note: Phase 9.4 will align Neovim editor settings (tabstop, shiftwidth, expandtab) with formatter configurations ## Phase 9.2 — none-ls setup with project-aware executables - [x] Add `nvimtools/none-ls.nvim` - [x] Create helper function to detect project-local executables (node_modules/.bin/, vendor/bin/, Mason bin) - [x] Configure formatters: - [x] prettier (project-local first, then Mason, then global) - [x] phpcbf (project-local first, then global system install - already available) - [x] stylua (Mason installed) - [x] Add `mfussenegger/nvim-lint` for linting (none-ls removed most linters from builtins) - [x] Configure linters via nvim-lint: - [x] eslint_d (project-local first, then Mason, then global - daemon version for speed) - [x] phpcs (project-local first, then global system install - already available) - [x] markdownlint (Mason installed) - [x] Add format-on-save autocommand with toggle capability (`lt` to toggle) - [x] Add manual format keymaps: `lf` (buffer), `lf` (visual range) - [x] Ensure WordPress coding standards work via phpcs.xml or --standard flag - [x] Search order: project node_modules/.bin/ → project vendor/bin/ → Mason bin → system PATH - [x] Note: Linting runs on BufEnter, BufWritePost, InsertLeave events ## Phase 9.3 — Mason formatter/linter installation - [x] Add `WhoIsSethDaniel/mason-tool-installer.nvim` for automated installation - [x] Install via Mason: prettier, eslint_d, markdownlint, stylua, black, ruff - [x] Note: phpcs/phpcbf already installed globally, skip Mason installation - [x] Verify all tools available: Tools installed to ~/.local/share/nvim/mason/bin/ ## Phase 9.4 — Align Neovim settings with formatter rules - [x] Configure per-filetype settings to match formatter defaults - [x] PHP: tabs, 2-width display (WordPress standards) - [x] JS/TS/CSS/JSON/HTML: spaces, 2-width (Prettier defaults) - [x] Lua: spaces, 2-width (common Neovim convention) - [x] Markdown: spaces, 2-width (Prettier defaults) - [x] Python: spaces, 4-width (Black/PEP 8 defaults) - [x] Use autocmds in lua/autocmds.lua for filetype-specific tabstop, shiftwidth, expandtab - [x] Set global defaults: 4-width, spaces (reasonable baseline) - [x] Goal: Manual editing feels natural and matches what formatter will produce on save - [x] Note: All settings kept explicit per-filetype for clarity and maintainability ## Phase 10 — Migrate Kept Behaviours ## Phase 10.1 — Confirm scope and priorities - [x] Confirm scope and priorities for this phase - [x] Decision: Port abbreviations to Lua via vim.cmd.iabbrev - [x] Decision: Port shell template auto-loading via autocmd + BufReadPost - [x] Decision: Whitespace highlighting already handled via listchars (Phase 3.2) - [x] Decision: Skip persistent folds (UFO handles folding, no explicit persistence needed) ## Phase 10.2 — Abbreviations - [x] Abbreviations: `adn→and`, `waht→what`, `tehn→then`, `functin→function`, `positin→position` - [x] Created dedicated `lua/abbreviations.lua` for modularity and easier maintenance ## Phase 10.3 — Templates - [x] Templates: auto-populate new `.sh` from template - [x] Added BufNewFile autocmd for *.sh in lua/autocmds.lua ## Phase 10.4 — Whitespace highlighting - [x] Whitespace highlighting (modern approach) - [x] Note: Already handled via listchars in Phase 3.2 (settings.lua) ## Phase 10.5 — Persistent folds - [x] Persistent folds (via UFO) -- no need, this is no longer required. - [x] Note: UFO handles folding; no explicit persistence mechanism needed ## Phase 11 — Colorscheme: Modern Paper Tonic ## Phase 11.1 — Confirm scope and priorities - [x] Confirm scope and priorities for this phase - [x] Decision: Create modern Paper Tonic fork from scratch - [x] Decision: Name = "paper-tonic-modern" - [x] Decision: Location = inside nvim config initially, move to repo later - [x] Decision: Structure = modular Lua colorscheme (colors.lua, groups/*.lua) - [x] Phased approach: - Phase 11.2-11.4: Extract palette and base groups - Phase 11.5-11.6: General TreeSitter highlights (modern @* groups) - Phase 11.7: Semantic highlighting (custom CSS/HTML captures) - Phase 11.8: Plugin support (LSP, Telescope, Gitsigns, etc.) ## Phase 11.2 — Extract Paper Tonic color palette - [x] Create `lua/paper-tonic-modern/colors.lua` - [x] Extract all `c_*` color variables from Paper Tonic - [x] Document what each color represents (foreground, background, accent colors) - [x] Convert to modern format (keep hex, 256-color, ANSI mappings) ## Phase 11.3 — Create colorscheme structure - [ ] Create directory structure: - `colors/paper-tonic-modern.lua` (entry point) - `lua/paper-tonic-modern/init.lua` (main logic) - `lua/paper-tonic-modern/colors.lua` (palette) - `lua/paper-tonic-modern/groups/` (highlight group definitions) - [ ] Create helper function for setting highlights - [ ] Set up colorscheme loading mechanism ## Phase 11.4 — Base vim highlight groups - [ ] Create `lua/paper-tonic-modern/groups/editor.lua` - [ ] Map Paper Tonic colors to base groups: Normal, Comment, LineNr, CursorLine, etc. - [ ] Create `lua/paper-tonic-modern/groups/syntax.lua` - [ ] Map to syntax groups: Function, String, Keyword, Identifier, etc. - [ ] Test with simple Lua file to verify base colors work ## Phase 11.5 — Modern TreeSitter highlight groups - [ ] Create `lua/paper-tonic-modern/groups/treesitter.lua` - [ ] Map modern `@*` groups to Paper Tonic colors: - Core: @variable, @function, @keyword, @string, @number, @boolean, @comment - Types: @type, @property, @field, @parameter - Operators: @operator, @punctuation.delimiter, @punctuation.bracket - Language constructs: @keyword.function, @keyword.return, @keyword.conditional - [ ] Use `:help treesitter-highlight-groups` as reference - [ ] Test with multiple languages: Lua, PHP, JavaScript, HTML, CSS ## Phase 11.6 — Language-specific TreeSitter groups - [ ] Add language-specific overrides (e.g., @variable.php, @tag.html) - [ ] Ensure HTML tags, CSS selectors, PHP variables have appropriate colors - [ ] Test across primary languages (HTML, PHP, JS, CSS, Markdown) ## Phase 11.7 — Semantic highlighting (custom captures) - [ ] Create `lua/paper-tonic-modern/groups/semantic.lua` - [ ] Define your custom semantic captures: - @CssClassName (for CSS .class and HTML class="" - same color) - @CssIdentifier (for CSS #id and HTML id="" - same color) - @DataAttribute, @DataAttributeValue (HTML data-* attributes) - @cssPseudoClass, @cssNestingSelector, @CssUniversalSelector (CSS-specific) - [ ] Verify cross-language consistency: class names in HTML match CSS - [ ] Test with existing custom queries (after/queries/css/highlights.scm, after/queries/html/highlights.scm) ## Phase 11.8 — Plugin highlight groups - [ ] Create `lua/paper-tonic-modern/groups/lsp.lua` - [ ] Define LSP diagnostics: DiagnosticError, DiagnosticWarn, DiagnosticHint, DiagnosticInfo - [ ] Define LSP UI: LspReferenceText, LspReferenceRead, LspReferenceWrite - [ ] Create `lua/paper-tonic-modern/groups/plugins.lua` - [ ] Add Telescope highlights (TelescopeNormal, TelescopeBorder, TelescopeSelection) - [ ] Add Gitsigns highlights (GitSignsAdd, GitSignsChange, GitSignsDelete) - [ ] Add nvim-cmp highlights (CmpItemKind*, CmpItemMenu, etc.) - [ ] Add Oil.nvim highlights if needed ## Phase 11.9 — Update plugin configuration - [ ] Update `lua/plugins/colorscheme.lua` to use paper-tonic-modern - [ ] Remove old Paper Tonic reference - [ ] Remove colorscheme-overrides.lua (no longer needed) - [ ] Test full config reload ## Phase 11.10 — Validation and polish - [ ] Test all primary languages (Lua, PHP, HTML, CSS, JS, Markdown) - [ ] Verify semantic consistency (CSS classes in HTML match CSS files) - [ ] Check plugin UI colors (Telescope, Gitsigns, nvim-cmp) - [ ] Verify LSP diagnostics are visible and distinct - [ ] Document color scheme in README ## Phase 11.11 — Extract to separate repo (later) - [ ] Move to `~/projects/paper-tonic-modern/` - [ ] Update plugin config to point to new location - [ ] Add proper README, LICENSE, screenshots - [ ] Consider publishing to GitHub ## Phase 12 — Cleanup & Validation ## Phase 12.1 — Confirm scope and priorities - [ ] Confirm scope and priorities for this phase ## Phase 12.2 — Retire legacy files - [ ] Retire legacy Vimscript files (keep for reference until verified) ## Phase 12.3 — Startup performance - [ ] Validate startup performance (no errors, fast launch) ## Phase 12.4 — Navigation validation - [ ] Validate Telescope navigation + LSP jumps - [ ] Validate netrw browsing and preview splits - [ ] Validate Oil.nvim file operations ## Phase 12.5 — Language tooling validation - [ ] Validate HTML/PHP/JS/Markdown tooling - [ ] Verify LSP (gd, gr, K, diagnostics) - [ ] Verify formatting (prettier, phpcbf, stylua) - [ ] Verify linting (eslint_d, phpcs, markdownlint) ## Phase 12.6 — Final polish - [ ] Review all keymaps and ensure they're documented - [ ] Update README.md with final architecture and usage - [ ] Clean up any remaining debug code or temporary comments --- Notes: - Keep plugin specs minimal; configure in their own `lua/plugins/*.lua` files. - Avoid adding plugins not listed in the guide unless explicitly requested. - Prefer simple defaults; only add settings that clearly improve workflow. - Plugin approval policy: unlisted plugins may be proposed, but must be explicitly confirmed before installation. Known Issues / Follow-ups: - lua-language-server (lua_ls) from Mason failed to start due to missing shared library `libbfd-2.38-system.so`. Options: - Install lua-language-server via system package manager compatible with your distro. - Provide the required `libbfd` or adjust symlink to match expected soname. - Skip lua_ls for now; validation done with other servers (jsonls, intelephense). - LSP root detection: In some cases, the parent repository is picked as the root (e.g., when a workspace lives inside another repo). Workaround: create an empty `.git` directory (or a marker like `.nvimroot`) in the intended workspace root to pin the project root for LSPs. Decisions & Changes: - **Neoconf dropped**: folke/neoconf.nvim incompatible with Neovim 0.11+ vim.lsp.config API (GitHub issue #116, open since May 2024, no resolution). Migrated to native `exrc` + `secure` approach. - **vim.lsp.config migration**: Migrated from deprecated `require('lspconfig')[server].setup()` to `vim.lsp.config()` + `vim.lsp.enable()` (Neovim 0.11+ native API). - **Project config format**: `.nvim.lua` files return `{ lsp = { [server_name] = { settings = {...} } } }`. - **Security model**: `secure` mode prompts user to trust `.nvim.lua` files before execution (one-time per file hash). - **Settings loading**: `on_new_config` hook loads project settings from actual `root_dir` (not cwd), ensuring correct behavior across different workspace structures. - **Phase 4 Navigation Strategy**: Skipped Neo-tree in favor of built-in netrw for visual context and project structure browsing. Telescope for fuzzy finding. Oil.nvim for file manipulation (evaluation phase; alternative is mini.files). Rationale: User needs visual context and preview, not per-tab roots or complex tree features. File manipulation primarily done in shell, but Oil.nvim handles buffer sync issues when renaming/moving files.