Skip to content

Nvim revamp - #376

Merged
shunkakinoki merged 27 commits into
mainfrom
nvim-revamp
Nov 28, 2025
Merged

Nvim revamp#376
shunkakinoki merged 27 commits into
mainfrom
nvim-revamp

Conversation

@shunkakinoki

@shunkakinoki shunkakinoki commented Nov 28, 2025

Copy link
Copy Markdown
Owner

Note

Major Neovim revamp: split config into Lua modules, switch to nvim-cmp, add terminal/AI/UI/search tooling; add Stylua to treefmt/flake and update Nix/macOS packages; add Biome/TypeScript deps.

  • Neovim:
    • Modularization: Replace monolithic init.lua with modules (lua/settings, plugins, autocmds, keymaps, lsp, telescope, treesitter, completion, ai, terminal, ui, utils).
    • Completion: Migrate to nvim-cmp with copilot-cmp and LuaSnip (replacing prior setup); add cmdline and gitcommit sources.
    • LSP/Diagnostics: Configure gopls, vtsls, lua_ls, etc., with cmp_nvim_lsp capabilities and unified diagnostics; add vim-illuminate.
    • UI/Workflow: Add which-key, trouble, lualine, notify, auto-dark-mode, oil, flash; enhance nvim-tree bindings; enable colorizer.
    • Search: Configure telescope with fzf and ui-select extensions and keymaps.
    • Treesitter: Expand parsers (incl. tsx, typescript, nix) and enable autopairs, autotag, surround, context, todo-comments, treesj.
    • Terminal: Manage terminals via toggleterm with primary/secondary toggles and cycling.
    • AI: Integrate sidekick.nvim via lua/ai.lua.
    • Format/Lint: conform.nvim (Biome/Stylua/Go/Nix), nvim-lint, and grug-far.
  • Tooling/Nix:
    • Add Stylua formatter to treefmt.toml and wire in flake.nix (pkgs.stylua).
    • Extract isCI to lib/env.nix; add speedtest-cli to packages.
    • macOS: update Homebrew casks (add visual-studio-code@insiders, switch to tailscale-app) and Dock apps (include Tailscale and VS Code Insiders).
  • Dependencies:
    • Add @biomejs/biome, typescript, and @typescript/native-preview in package.json.

Written by Cursor Bugbot for commit f35831e. Configure here.


Summary by cubic

Revamps Neovim into a modular Lua setup with improved editing, navigation, and terminal workflows. Also updates formatting and dev tooling across Nix and package configs.

  • New Features

    • Autocmds for yank highlight, split resize, file change checks, and git commit insert.
    • Completion via nvim-cmp with LuaSnip and Copilot integration.
    • LSP setup with keymaps and diagnostics.
    • Telescope with fzf and ui-select, using ivy themes.
    • Treesitter extras: indent guides, autopairs, autotag, surround, TODO highlights, and context.
    • UI upgrades: dressing, notify, lualine, nvim-tree, colorizer, gitsigns, which-key.
    • Terminal management with toggleterm (horizontal layout, multi-terminal toggle/cycle).
    • Streamlined keymaps for quickfix, buffers, git, and navigation.
  • Refactors & Dependencies

    • Split init.lua into modules: settings, keymaps, plugins, lsp, completion, telescope, treesitter, ui, terminal, autocmds, utils, workspace.
    • Added Stylua to treefmt and flake for Lua formatting.
    • Extracted isCI to lib/env.nix; included speedtest-cli in packages.
    • Updated dependencies and lockfiles (TypeScript, Biome, TS native preview).
    • macOS: dock adds Tailscale and VS Code Insiders; Homebrew cask switched to tailscale-app; added Trae to casks.

Written for commit 69ceac0. Summary will update automatically on new commits.

- Implemented various autocmds for improved user experience, including:
  - Highlighting on yank
  - Resizing splits on window resize
  - Automatic file change checks
  - Git commit message enhancements
  - Ensuring parent directories exist for new files
  - Help window positioning
  - Git and Fugitive buffer configurations

- Integrated completion setup using nvim-cmp and copilot, with custom mappings for snippets and sources.

- Established key mappings for efficient navigation, buffer management, and Git operations.

- Configured LSP with multiple language servers and diagnostic settings, including custom signs for diagnostics.

- Added plugin management with a focus on UI enhancements, coding tools, and Treesitter support.

- Set up user interface elements including lualine, nvim-tree, and notification handling.

- Enhanced Treesitter configuration with various language support and text object mappings.

- Implemented terminal management with toggleterm for better terminal integration.

- Created utility functions for buffer cycling and quickfix management.
Copilot AI review requested due to automatic review settings November 28, 2025 05:06
@coderabbitai

coderabbitai Bot commented Nov 28, 2025

Copy link
Copy Markdown

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced code editor with integrated AI assistance, improved completion system, and integrated terminal management
    • Comprehensive keybinding system for improved navigation and git operations
    • Better code diagnostics and formatting support
  • Updates

    • Added development dependencies for code quality and formatting tools
    • Updated system applications and package configurations for development environments
    • Reorganized editor configuration for improved maintainability

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

Adds a Lua formatter (Stylua) to treefmt config, centralizes CI detection in lib/env.nix and uses it in Home Manager conditionals, and refactors a large monolithic Neovim config into modular Lua modules with many new plugins and utilities; also updates macOS dock/homebrew casks and project dependencies.

Changes

Cohort / File(s) Summary
Formatter & Treefmt
flake.nix, treefmt.toml
Add Lua formatter entry wired to stylua in treefmtSettings and add [formatter.lua] in treefmt.toml.
Environment & Package Conditionals
lib/env.nix, home-manager/packages/default.nix
Add lib/env.nix exporting isCI; import isCI in Home Manager, add speedtest-cli, and add platform/CI-based lib.optionals package lists.
Neovim — init and modules
home-manager/programs/neovim/init.lua, home-manager/programs/neovim/lua/*, home-manager/programs/neovim/nvim-pack-lock.json
Replace monolithic init.lua with modular loader and add many modules (ai, autocmds, completion, keymaps, lsp, plugins, settings, telescope, terminal, treesitter, ui, utils, workspace); add/lock 20+ plugins in pack lock.
macOS configuration
nix-darwin/config/dock.nix, nix-darwin/config/homebrew.nix
Add Tailscale and VS Code Insiders to Dock; update Homebrew casks (trae, visual-studio-code@insiders, tailscaletailscale-app).
Project dependencies
package.json
Add @biomejs/biome, @getgrit/cli, @typescript/native-preview, and typescript; update trustedDependencies.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Pay special attention to Neovim modularization: module path handling, side effects during init, and exported utilities (terminal API, utils.cycle_buffer).
  • Verify LSP and completion server configurations and potential keymap conflicts.
  • Confirm isCI semantics in lib/env.nix and conditional package inclusion correctness.
  • Ensure flake.nix formatter wiring uses a resolvable pkgs.stylua and matches treefmt.toml.

Possibly related PRs

Poem

🐰✨ I hopped through code with nimble feet,
Stylua tidied every Lua sheet,
Modules sewn from a single seam,
Plugins chimed in — a dev-rabbit dream,
🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.88% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title "Nvim revamp" is vague and generic, using a non-descriptive term that doesn't convey meaningful information about the specific nature of the extensive changes. Consider using a more descriptive title that captures the main focus, such as "Refactor Neovim config to modular Lua structure" or "Modularize Neovim configuration with new LSP and UI improvements".
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The description provides comprehensive details about the changes, including specific modules, plugins, and tooling updates that align with the changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch nvim-revamp

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f91c8cb and 69ceac0.

📒 Files selected for processing (1)
  • home-manager/programs/neovim/lua/workspace.lua (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • home-manager/programs/neovim/lua/workspace.lua
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: docker-build-push (linux/arm64, arm64, ubuntu-24.04-arm)
  • GitHub Check: docker-build-push (linux/amd64, amd64, ubuntu-latest)
  • GitHub Check: e2e-run (Ubuntu, ubuntu-latest)
  • GitHub Check: e2e-run (NixOS, ubuntu-latest)
  • GitHub Check: e2e-run (MacOS, macos-latest)
  • GitHub Check: nix-nixos
  • GitHub Check: nix-linux
  • GitHub Check: nix-darwin
  • GitHub Check: nix-flake
  • GitHub Check: lua-hammerspoon
  • GitHub Check: lua-neovim

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@mesa-dot-dev

mesa-dot-dev Bot commented Nov 28, 2025

Copy link
Copy Markdown

You do not have enough credits to review this pull request. Please purchase more credits to continue.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @shunkakinoki, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a comprehensive revamp of the Neovim configuration, moving from a monolithic init.lua to a highly modular and organized structure. This architectural change significantly enhances the maintainability and extensibility of the Neovim setup. Alongside this refactoring, a suite of new plugins and tools has been integrated to provide a more robust and efficient development environment, covering areas such as code completion, AI assistance, terminal management, advanced navigation, and improved diagnostics. The update also includes essential dependency additions and Nix configuration adjustments to support these new features and maintain a consistent development ecosystem.

Highlights

  • Neovim Configuration Modularization: The monolithic init.lua file has been completely refactored into a set of dedicated Lua modules (settings, plugins, autocmds, keymaps, lsp, telescope, treesitter, completion, ai, terminal, ui, utils) for improved organization and maintainability.
  • New Development Tools Integration: Several new tools and plugins have been integrated to enhance the development experience, including nvim-cmp for advanced completion, copilot-cmp for Copilot integration, sidekick.nvim for AI workspace, toggleterm.nvim for enhanced terminal management, flash.nvim for improved navigation, trouble.nvim for diagnostics, oil.nvim for file browsing, and grug-far.nvim for search/replace.
  • Dependency Updates and Additions: New dependencies such as @biomejs/biome, @typescript/native-preview, and typescript were added to bun.lock and package.json. Additionally, stylua (for Lua formatting) and speedtest-cli were added to Nix packages.
  • Nix Configuration Enhancements: The Nix configuration was updated to include stylua for Lua formatting in flake.nix, refactor the isCI variable into a separate lib/env.nix module, and add new applications (Tailscale.app, Visual Studio Code Insiders.app) to Nix-Darwin configurations.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@mesa-dot-dev

mesa-dot-dev Bot commented Nov 28, 2025

Copy link
Copy Markdown

Mesa Description

TL;DR

Major Neovim revamp: split config into Lua modules, switch to nvim-cmp, add terminal/AI/UI/search tooling; add Stylua to treefmt/flake and update Nix/macOS packages; add Biome/TypeScript deps.

What changed?

  • Neovim Configuration:
    • home-manager/programs/neovim/init.lua: Refactored into a modular loader, dynamically loading individual configuration modules.
    • home-manager/programs/neovim/lua/ai.lua: New file integrating and configuring sidekick.nvim for an AI workspace.
    • home-manager/programs/neovim/lua/autocmds.lua: New file introducing comprehensive autocommands for yank highlight, split resizing, file change detection, and filetype-specific configurations.
    • home-manager/programs/neovim/lua/completion.lua: New file configuring nvim-cmp with copilot-cmp, LuaSnip, and various completion sources.
    • home-manager/programs/neovim/lua/keymaps.lua: New file introducing a comprehensive set of keymaps for Quickfix, buffers, terminal, navigation, Git, and editing.
    • home-manager/programs/neovim/lua/lsp.lua: New file establishing a comprehensive LSP configuration for multiple language servers and diagnostic display options.
    • home-manager/programs/neovim/lua/plugins.lua: New file setting up a comprehensive plugin configuration using vim.pack.add, including conform.nvim and nvim-lint.
    • home-manager/programs/neovim/lua/settings.lua: New file setting up core Neovim configurations for editing, UI, search, and terminal.
    • home-manager/programs/neovim/lua/telescope.lua: New file configuring telescope.nvim with fzf, ui-select extensions, and extensive keybindings.
    • home-manager/programs/neovim/lua/terminal.lua: New file configuring toggleterm.nvim for primary/secondary horizontal terminals and cycling functions.
    • home-manager/programs/neovim/lua/treesitter.lua: New file introducing Treesitter configuration with numerous language parsers and related plugins like indent-blankline, nvim-autopairs, nvim-ts-autotag, nvim-surround, todo-comments.nvim, and treesitter-context.
    • home-manager/programs/neovim/lua/ui.lua: New file establishing a comprehensive Neovim UI configuration by integrating multiple plugins for prompts, notifications, statusline, dark mode, file explorer, and diagnostics.
    • home-manager/programs/neovim/lua/utils.lua: New utility file introducing Lua functions for cycling buffers and managing the quickfix list.
    • home-manager/programs/neovim/nvim-pack-lock.json: Updated Neovim plugin versions and dependencies.
  • Nix/System Configuration:
    • flake.nix: Added Lua formatting using stylua to the treefmt configuration.
    • home-manager/packages/default.nix: Imported isCI from lib/env.nix and added speedtest-cli to installed packages.
    • lib/env.nix: New file defining an isCI attribute to detect Continuous Integration environments.
    • nix-darwin/config/dock.nix: Updated Dock configuration to include "Tailscale.app" and "Visual Studio Code Insiders.app".
    • nix-darwin/config/homebrew.nix: Updated Homebrew casks to include 'visual-studio-code@insiders' and replace 'tailscale' with 'tailscale-app'.
  • Dependencies:
    • bun.lock: Updated to reflect changes in project dependencies.
    • package.json: Added @biomejs/biome, @typescript/native-preview, typescript, and @getgrit/cli as new development dependencies and to trustedDependencies.
    • treefmt.toml: Added a new Lua formatter using stylua.

Description generated by Mesa. Update settings

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +40 to +45
for name, config in pairs(servers) do
config.on_attach = on_attach
config.capabilities = capabilities
vim.lsp.config(name, config)
end
vim.lsp.enable(vim.tbl_keys(servers))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge LSP setup uses nonexistent vim.lsp API

The new LSP bootstrap calls vim.lsp.config(name, config) and vim.lsp.enable(...), but the stock pkgs.neovim build used in home-manager/programs/neovim/default.nix does not expose those functions; the supported entrypoints remain require('lspconfig').<server>.setup(...) or vim.lsp.start. On current releases this code raises attempt to call field 'config' (a nil value) when lsp.lua is required, so no servers are registered and Neovim init halts before the rest of the modules run.

Useful? React with 👍 / 👎.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request is a major and impressive refactoring of the Neovim configuration. It moves from a large, monolithic init.lua to a well-structured, modular setup with separate files for settings, plugins, keymaps, LSP, and more. This greatly improves maintainability and readability. The addition of new plugins like toggleterm, trouble, and flash, along with the switch to nvim-cmp, modernizes the editing experience. The Nix configuration changes are also clean and improve organization. My review includes a few suggestions to further improve modularity and address some minor regressions or code smells introduced during the refactoring. Overall, this is an excellent update.

Comment on lines +16 to +18
local config_lua_path = vim.fn.stdpath("config") .. "/lua/?.lua"
append_package_path(config_lua_path)
append_package_path(vim.fn.stdpath("config") .. "/lua/?/init.lua")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic to determine the script's directory and add the lua subdirectory to package.path (lines 20-27) is robust and should be sufficient on its own. The preceding lines that add paths relative to vim.fn.stdpath("config") are likely redundant, as init_dir and vim.fn.stdpath("config") should point to the same location in a typical setup. Removing this redundant setup would make the configuration cleaner.

Comment on lines +65 to +66
[vim.diagnostic.severity.ERROR] = "",
[vim.diagnostic.severity.WARN] = "",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The diagnostic signs for ERROR and WARN levels are configured as empty strings. This disables visual indicators in the sign column for errors and warnings, which is a regression from the previous configuration and reduces the at-a-glance visibility of code issues. I recommend re-enabling them to improve the debugging experience. You could restore the previous icons or use alternatives.

			[vim.diagnostic.severity.ERROR] = "",
			[vim.diagnostic.severity.WARN] = "",

Comment on lines +126 to +130
vim.api.nvim_create_autocmd({ "BufWritePost" }, {
callback = function()
lint.try_lint()
end,
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This autocmd for nvim-lint is defined in plugins.lua. For better organization and maintainability, all autocmds should be centralized in autocmds.lua. Please move this block to autocmds.lua.

Comment on lines +50 to +51
-- Suppress deprecation warnings (temporary until plugins update)
vim.deprecate = function() end

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Suppressing all deprecation warnings by overriding vim.deprecate can hide important information about outdated APIs used by plugins. While the comment indicates this is temporary, this is a form of technical debt that should be tracked more formally, for instance with a TODO comment, to ensure it gets addressed.

-- TODO: Remove this once plugins are updated to not use deprecated APIs
vim.deprecate = function() end

Comment on lines +1 to +94
-- Manage Neovim-hosted terminals with floating/split layouts.
-- From: https://github.com/akinsho/toggleterm.nvim
local toggleterm = require("toggleterm")
-- Expose the toggleterm terminal constructor for custom instances.
-- From: https://github.com/akinsho/toggleterm.nvim
local Terminal = require("toggleterm.terminal").Terminal

toggleterm.setup({
direction = "horizontal",
size = function(term)
if term.direction == "horizontal" then
return math.floor(vim.o.lines * 0.3)
end
return 20
end,
start_in_insert = true,
shade_terminals = true,
persist_size = true,
})

local function create_term(count)
return Terminal:new({
direction = "horizontal",
count = count,
hidden = true,
on_open = function()
vim.cmd("startinsert!")
end,
})
end

local term_sequence = { 1, 2 }
local terms = {
[1] = create_term(1),
[2] = create_term(2),
}
local current_index = 1

local function index_of(count)
for idx, value in ipairs(term_sequence) do
if value == count then
return idx
end
end
return 1
end

local function toggle_term(count)
for other_count, term in pairs(terms) do
if other_count ~= count and term:is_open() then
term:close()
end
end

local term = terms[count]
term:toggle()
if term:is_open() then
current_index = index_of(count)
end
end

function TogglePrimaryTerm()
toggle_term(1)
end

function ToggleSecondaryTerm()
toggle_term(2)
end

local function cycle(step)
local len = #term_sequence
current_index = ((current_index - 1 + step) % len) + 1
local next_count = term_sequence[current_index]
local term = terms[next_count]
if not term:is_open() then
toggle_term(next_count)
else
for _, t in pairs(terms) do
if t ~= term and t:is_open() then
t:close()
end
end
term:close()
term:open()
end
end

function CycleNextTerm()
cycle(1)
end

function CyclePreviousTerm()
cycle(-1)
end

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This module defines several functions like TogglePrimaryTerm and CycleNextTerm in the global scope, which are then called from keymaps.lua. This pollutes the global namespace and can lead to name collisions. A better practice is to return these functions in a table from the module and explicitly require and use them in keymaps.lua, similar to how utils.lua is structured and used.

For example, in terminal.lua:

local M = {}
-- ... existing local functions ...
function M.TogglePrimaryTerm()
  toggle_term(1)
end
-- ... other functions on M ...
return M

And in keymaps.lua:

local terminal = require("terminal")
-- ...
keymap({ "n", "t" }, "<leader>j", function()
	teminal.TogglePrimaryTerm()
end, opts)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR represents a major refactoring of the Neovim configuration, transitioning from a monolithic 1330-line init.lua to a modular architecture with separate configuration files. The refactoring improves maintainability and organization while switching from blink.cmp to nvim-cmp for completion, and adding several new plugins for enhanced functionality.

Key Changes

  • Modularized Neovim configuration: Split the massive init.lua into 12 focused modules (settings, plugins, autocmds, keymaps, lsp, telescope, treesitter, completion, ai, terminal, ui, utils)
  • Completion engine migration: Replaced blink.cmp with nvim-cmp ecosystem (including nvim-cmp, cmp-nvim-lsp, cmp-buffer, cmp-path, cmp-cmdline, LuaSnip, cmp_luasnip, copilot-cmp)
  • New plugins added: toggleterm.nvim for terminal management, trouble.nvim for diagnostics, which-key.nvim for keybinding hints, fidget.nvim for LSP progress, oil.nvim for file navigation, flash.nvim for motion jumping, grug-far.nvim for search/replace, telescope extensions (fzf-native, ui-select), nvim-lint, nvim-vtsls, and vim-illuminate

Reviewed changes

Copilot reviewed 22 out of 23 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
home-manager/programs/neovim/init.lua Drastically simplified to 43 lines; now only sets leader key, configures module paths, and requires all modular components
home-manager/programs/neovim/lua/settings.lua Extracted all vim options and settings from init.lua into dedicated module
home-manager/programs/neovim/lua/plugins.lua Centralized plugin declarations using vim.pack.add with setup calls for various plugins
home-manager/programs/neovim/lua/keymaps.lua Consolidated all keymaps including buffer operations, terminal toggles, navigation, git operations, and diagnostics
home-manager/programs/neovim/lua/lsp.lua LSP configuration with on_attach keymaps and server setup using new vim.lsp.config/enable API
home-manager/programs/neovim/lua/completion.lua nvim-cmp setup with LSP, Copilot, LuaSnip, buffer, and path sources; replaces blink.cmp configuration
home-manager/programs/neovim/lua/telescope.lua Telescope configuration with ivy theme, fzf extension, and various picker keymaps
home-manager/programs/neovim/lua/treesitter.lua Treesitter setup with syntax highlighting, indentation, autopairs, and textobject navigation
home-manager/programs/neovim/lua/terminal.lua toggleterm.nvim configuration with functions for managing multiple terminal instances
home-manager/programs/neovim/lua/ui.lua UI plugin setup including lualine, nvim-tree, which-key, fidget, oil, trouble, auto-dark-mode, dressing, and notify
home-manager/programs/neovim/lua/autocmds.lua All autocommands for highlight on yank, window resize, git workflows, file type settings, etc.
home-manager/programs/neovim/lua/utils.lua Utility functions for buffer cycling and quickfix list management
home-manager/programs/neovim/lua/ai.lua Simple sidekick.nvim setup for AI workspace integration
home-manager/programs/neovim/nvim-pack-lock.json Added 19 new plugins for completion, linting, navigation, and UI enhancements
treefmt.toml Added stylua formatter for Lua files
flake.nix Added stylua formatter configuration in treefmt setup
package.json Added @biomejs/biome, @typescript/native-preview, and typescript dependencies; reordered entries
bun.lock Updated lockfile with new dependency entries and trust relationships
nix-darwin/config/homebrew.nix Changed 'tailscale' to 'tailscale-app' (correct cask name); added 'visual-studio-code@insiders'
nix-darwin/config/dock.nix Added Tailscale.app and Visual Studio Code Insiders.app to dock
home-manager/packages/default.nix Moved isCI environment detection to lib/env.nix; added speedtest-cli package
lib/env.nix New shared module for environment detection (CI/Docker)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +100 to +101
-- @keymap i: Open in horizontal split (nvim-tree)
vim.keymap.set("n", "i", api.node.open.horizontal, opts("Open: Horizontal Split"))

Copilot AI Nov 28, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate keymap functionality: Both 's' (line 96-97) and 'i' (line 100-101) are mapped to the same action api.node.open.horizontal (Open: Horizontal Split). This appears to be redundant. Consider removing one of these mappings or assigning 'i' to a different action if that was intended.

Suggested change
-- @keymap i: Open in horizontal split (nvim-tree)
vim.keymap.set("n", "i", api.node.open.horizontal, opts("Open: Horizontal Split"))

Copilot uses AI. Check for mistakes.
local flash = require("flash")

-- @keymap <Space>: Set as leader key
--Remap space as leader key

Copilot AI Nov 28, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing space after comment delimiter. Should be -- Remap space as leader key (with a space after --).

Suggested change
--Remap space as leader key
-- Remap space as leader key

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,71 @@
-- Keymaps for LSP actions in on_attach
local on_attach = function(client, bufnr)

Copilot AI Nov 28, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The client parameter in the on_attach function is defined but never used. Consider prefixing it with an underscore (_client) to indicate it's intentionally unused, or remove it if it's not needed for the function signature.

Suggested change
local on_attach = function(client, bufnr)
local on_attach = function(_client, bufnr)

Copilot uses AI. Check for mistakes.
vim.opt.termsync = true
vim.opt.hidden = true
vim.opt.updatetime = 300
vim.opt.mouse = "a"

Copilot AI Nov 28, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mouse setting has been changed from disabled ("") to enabled ("a"). In the old init.lua, mouse was set to vim.opt.mouse = "" (disabled), but now it's set to "a" (enabled in all modes). This is a significant behavior change that may not be intentional.

If this change was intentional, it should be noted in the PR description. Otherwise, consider reverting to vim.opt.mouse = "".

Suggested change
vim.opt.mouse = "a"
vim.opt.mouse = ""

Copilot uses AI. Check for mistakes.
Comment thread package.json
Comment on lines +14 to +22
"@biomejs/biome": "^2.3.8",
"@getgrit/cli": "^0.1.0-alpha.1743007075",
"@github/copilot": "^0.0.365",
"@google/jules": "^0.1.40",
"@getgrit/cli": "^0.1.0-alpha.1743007075",
"@nanocollective/nanocoder": "^1.16.3",
"@typescript/native-preview": "^7.0.0-dev.20251127.1",
"cline": "^1.0.5",
"open-composer": "^0.8.23"
"open-composer": "^0.8.23",
"typescript": "^5.9.3"

Copilot AI Nov 28, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Dependencies are not in alphabetical order. @biomejs/biome and @getgrit/cli have been moved to the top, but ideally all dependencies should be sorted alphabetically for better maintainability. Consider sorting them:

"@biomejs/biome": "^2.3.8",
"@getgrit/cli": "^0.1.0-alpha.1743007075",
"@github/copilot": "^0.0.365",
"@google/jules": "^0.1.40",
"@nanocollective/nanocoder": "^1.16.3",
"@typescript/native-preview": "^7.0.0-dev.20251127.1",
"cline": "^1.0.5",
"open-composer": "^0.8.23",
"typescript": "^5.9.3"

Copilot uses AI. Check for mistakes.
Comment on lines +62 to +94
function TogglePrimaryTerm()
toggle_term(1)
end

function ToggleSecondaryTerm()
toggle_term(2)
end

local function cycle(step)
local len = #term_sequence
current_index = ((current_index - 1 + step) % len) + 1
local next_count = term_sequence[current_index]
local term = terms[next_count]
if not term:is_open() then
toggle_term(next_count)
else
for _, t in pairs(terms) do
if t ~= term and t:is_open() then
t:close()
end
end
term:close()
term:open()
end
end

function CycleNextTerm()
cycle(1)
end

function CyclePreviousTerm()
cycle(-1)
end

Copilot AI Nov 28, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Global functions should be declared as local. These functions (TogglePrimaryTerm, ToggleSecondaryTerm, CycleNextTerm, CyclePreviousTerm) are used in keymaps.lua but are declared as global functions without the local keyword. This pollutes the global namespace and is not best practice in Lua.

Consider declaring them as local and returning them in a module table:

local M = {}
M.TogglePrimaryTerm = function() toggle_term(1) end
M.ToggleSecondaryTerm = function() toggle_term(2) end
M.CycleNextTerm = function() cycle(1) end
M.CyclePreviousTerm = function() cycle(-1) end
return M

Then in keymaps.lua, require the module: local terminal = require("terminal") and use terminal.TogglePrimaryTerm() instead.

Copilot uses AI. Check for mistakes.
vim.notify = notify

local section_b = { "branch", "diff", { "diagnostics", sources = { "nvim_workspace_diagnostic" } } }
local section_c = { "%=", { "filename", file_status = true, path = 1 } }

Copilot AI Nov 28, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file_status option has been changed from false to true compared to the original init.lua configuration. This will now show modified/readonly status indicators in the filename component of lualine. If this change was unintentional, consider reverting to file_status = false.

Suggested change
local section_c = { "%=", { "filename", file_status = true, path = 1 } }
local section_c = { "%=", { "filename", file_status = false, path = 1 } }

Copilot uses AI. Check for mistakes.
require("ai")
require("terminal")
require("ui")
require("utils")

Copilot AI Nov 28, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The utils module is required here but doesn't export anything (returns M module table). However, in keymaps.lua (line 3), it's required and used to call utils.cycle_buffer(). This works because the utils module does return M, but the require here in init.lua serves no purpose since nothing from utils is used in init.lua itself. Consider removing this line as utils is already properly loaded when keymaps.lua requires it.

Suggested change
require("utils")

Copilot uses AI. Check for mistakes.
Comment thread package.json
Comment on lines 22 to +33
"@biomejs/biome",
"@getgrit/cli",
"@github/copilot",
"@google/jules",
"@getgrit/cli",
"@nanocollective/nanocoder",
"@typescript/native-preview",
"cline",
"open-composer"
"open-composer",
"typescript"

Copilot AI Nov 28, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The trustedDependencies array is not sorted alphabetically (similar to the dependencies). This array has been reordered but not fully sorted. Consider maintaining alphabetical order:

"trustedDependencies": [
  "@biomejs/biome",
  "@getgrit/cli",
  "@github/copilot",
  "@google/jules",
  "@nanocollective/nanocoder",
  "@typescript/native-preview",
  "cline",
  "open-composer",
  "typescript"
]

Copilot uses AI. Check for mistakes.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (19)
nix-darwin/config/homebrew.nix (1)

89-89: Consider sorting tailscale-app alphabetically.

The cask tailscale-app is placed at the end of the list but should be positioned between "slack" and "visual-studio-code" for alphabetical consistency. Based on coding guidelines, configuration lists should be sorted alphabetically when possible.

       "slack"
+      "tailscale-app"
       "visual-studio-code"
       "visual-studio-code@insiders"
       "vscodium"
       "warp"
       "wezterm"
       "windsurf"
       "zed"
       "zoom"
-      "tailscale-app"
     ];
home-manager/programs/neovim/lua/autocmds.lua (4)

107-120: Window closes before async operation completes.

The vim.cmd("silent! close") executes immediately after starting vim.system, not after it completes. This can be confusing since the user sees the window close but success/error notifications may appear much later in a different context.

Consider moving the close inside the callback or awaiting completion:

 		vim.keymap.set("n", "gp", function()
-			async_git({ "push", "--quiet" }, "Pushed!", "Push failed!")
-			vim.cmd("silent! close")
+			vim.cmd("silent! close")
+			async_git({ "push", "--quiet" }, "Pushed!", "Push failed!")
 		end, buf_opts)

Or keep the window open until completion by moving close into the callback.


153-160: Empty placeholder callback.

The Terminal augroup has no functionality. Either add the intended terminal settings or remove the placeholder to avoid dead code.


32-44: Consolidate duplicate gitcommit autocmds.

These two autocmds for the same filetype can be merged into a single callback:

-autocmd("FileType", {
-	group = gitcommit_group,
-	pattern = "gitcommit",
-	command = "startinsert",
-})
-autocmd("FileType", {
-	group = gitcommit_group,
-	pattern = "gitcommit",
-	callback = function()
-		vim.opt_local.spell = true
-		vim.opt_local.textwidth = 72
-	end,
-})
+autocmd("FileType", {
+	group = gitcommit_group,
+	pattern = "gitcommit",
+	callback = function()
+		vim.cmd("startinsert")
+		vim.opt_local.spell = true
+		vim.opt_local.textwidth = 72
+	end,
+})

46-58: Minor: Simplify the reload command.

The :e % command has redundant syntax.

-			vim.cmd([[ :e % ]])
+			vim.cmd("edit %")
home-manager/programs/neovim/lua/telescope.lua (1)

57-67: Consider adding --exclude patterns to fd command.

The --hidden flag will include dotfiles, which is often desired. However, you may want to exclude common directories like .git, node_modules, etc., to avoid noise:

 	builtin.find_files(ivy({
 		find_command = {
 			"fd",
 			"--type",
 			"f",
 			"--strip-cwd-prefix",
 			"--hidden",
+			"--exclude",
+			".git",
 		},
 	}))

This is optional as fd respects .gitignore by default.

home-manager/programs/neovim/lua/completion.lua (1)

22-35: Tab navigation doesn't integrate with LuaSnip jump points.

The current Tab/S-Tab mappings only handle cmp visibility. Consider adding LuaSnip jump support for snippet placeholders:

 		["<Tab>"] = cmp.mapping(function(fallback)
+			local luasnip = require("luasnip")
 			if cmp.visible() then
 				cmp.select_next_item()
+			elseif luasnip.expand_or_jumpable() then
+				luasnip.expand_or_jump()
 			else
 				fallback()
 			end
 		end, { "i", "s" }),
 		["<S-Tab>"] = cmp.mapping(function(fallback)
+			local luasnip = require("luasnip")
 			if cmp.visible() then
 				cmp.select_prev_item()
+			elseif luasnip.jumpable(-1) then
+				luasnip.jump(-1)
 			else
 				fallback()
 			end
 		end, { "i", "s" }),
home-manager/programs/neovim/init.lua (1)

20-27: Consider using vim.uv instead of vim.loop.

vim.loop is deprecated in Neovim 0.10+ in favor of vim.uv. While it still works, updating ensures forward compatibility.

-local init_path = vim.loop.fs_realpath(init_source) or init_source
+local init_path = vim.uv.fs_realpath(init_source) or init_source
home-manager/programs/neovim/lua/settings.lua (1)

50-51: Suppressing all deprecation warnings may hide important issues.

Completely overwriting vim.deprecate to a no-op will silence all deprecation warnings, including those that indicate breaking changes in future Neovim versions. Consider a more targeted approach or at least add a TODO to revisit this.

 -- Suppress deprecation warnings (temporary until plugins update)
-vim.deprecate = function() end
+-- TODO: Remove once plugins are updated for Neovim 0.11+
+vim.deprecate = function() end

Alternatively, consider logging deprecations to a file instead of completely suppressing them.

home-manager/programs/neovim/lua/lsp.lua (2)

10-10: Consider using <leader>ca instead of bare ca for code action.

The ca mapping without a leader prefix may conflict with other mappings (like c for change followed by a) and is inconsistent with other leader-prefixed mappings like <leader>rn and <leader>D.

-	vim.keymap.set("n", "ca", vim.lsp.buf.code_action, opts)
+	vim.keymap.set("n", "<leader>ca", vim.lsp.buf.code_action, opts)

63-69: Clarify intent: Empty strings for ERROR, WARN, and INFO signs.

The diagnostic signs for ERROR, WARN, and INFO are set to empty strings while HINT has an icon. If this is intentional (relying on virtual text only for these severities), consider adding a brief comment explaining the design choice.

 	signs = {
 		text = {
+			-- Using virtual text for these severities; signs intentionally hidden
 			[vim.diagnostic.severity.ERROR] = "",
 			[vim.diagnostic.severity.WARN] = "",
 			[vim.diagnostic.severity.INFO] = "",
 			[vim.diagnostic.severity.HINT] = "󰌶",
 		},
 	},
home-manager/programs/neovim/lua/terminal.lua (3)

62-68: Consider using module exports instead of global functions.

Defining functions as globals (TogglePrimaryTerm, ToggleSecondaryTerm, etc.) pollutes the global namespace. Consider returning a module table instead.

-function TogglePrimaryTerm()
-	toggle_term(1)
-end
-
-function ToggleSecondaryTerm()
-	toggle_term(2)
-end
+local M = {}
+
+function M.toggle_primary()
+	toggle_term(1)
+end
+
+function M.toggle_secondary()
+	toggle_term(2)
+end

Then at the end of the file:

return M

Update keymaps to use require("terminal").toggle_primary().

Also applies to: 88-94


70-86: Redundant close/open when terminal is already open.

When cycling to a terminal that's already open (line 75), the code closes all other terminals, then closes and reopens the target terminal (lines 83-84). This causes unnecessary flicker. If the target is already open and focused, you may want to skip the close/open cycle.

 local function cycle(step)
 	local len = #term_sequence
 	current_index = ((current_index - 1 + step) % len) + 1
 	local next_count = term_sequence[current_index]
 	local term = terms[next_count]
 	if not term:is_open() then
 		toggle_term(next_count)
 	else
+		-- Terminal is already open; close others and refocus
 		for _, t in pairs(terms) do
 			if t ~= term and t:is_open() then
 				t:close()
 			end
 		end
-		term:close()
-		term:open()
+		-- Only reopen if we need to ensure insert mode
+		vim.cmd("startinsert!")
 	end
 end

10-15: Unreachable branch in size function.

The toggleterm.setup configures direction = "horizontal", and create_term also uses direction = "horizontal". The else branch returning 20 will never execute.

 	size = function(term)
-		if term.direction == "horizontal" then
-			return math.floor(vim.o.lines * 0.3)
-		end
-		return 20
+		return math.floor(vim.o.lines * 0.3)
 	end,

Or keep the branch if you plan to support vertical terminals in the future.

home-manager/programs/neovim/lua/ui.lua (2)

52-54: Consider using lualine.refresh() instead of full lualine.setup().

Calling lualine.setup() on every theme change reinitializes the entire plugin. If only the theme needs updating, lualine.refresh() may be more efficient.

 		-- Refresh lualine to update theme
 		if package.loaded["lualine"] then
-			lualine.setup(lualine_config)
+			require("lualine").refresh()
 		end

Note: Verify that refresh() properly picks up the new background value for the dynamic theme function.

Also applies to: 60-62


142-145: Minor: Inconsistent keymap comment for 'I'.

The comment says "Toggle dotfiles" but the action is toggle_hidden_filter. The comment for 'H' says "Toggle dotfiles" but maps to toggle_gitignore_filter. Consider updating for clarity.

-		-- @keymap H: Toggle dotfiles (nvim-tree)
+		-- @keymap H: Toggle git-ignored files (nvim-tree)
 		vim.keymap.set("n", "H", api.tree.toggle_gitignore_filter, opts("Toggle Git Ignore"))
-		-- @keymap I: Toggle dotfiles (nvim-tree)
+		-- @keymap I: Toggle hidden/dotfiles (nvim-tree)
 		vim.keymap.set("n", "I", api.tree.toggle_hidden_filter, opts("Toggle Dotfiles"))
home-manager/programs/neovim/lua/plugins.lua (1)

110-113: Consider increasing the format timeout for larger files.

The 500ms timeout might be insufficient for formatting large files, especially with formatters like black or biome that can be slower on complex codebases. Consider increasing to at least 1000-2000ms or making this configurable.

Apply this diff to increase the timeout:

 	format_on_save = {
-		timeout_ms = 500,
+		timeout_ms = 2000,
 		lsp_fallback = true,
 	},
home-manager/programs/neovim/lua/keymaps.lua (2)

46-46: Potentially destructive operation - wipes all buffers without confirmation.

The %bwipeout! command force-wipes all buffers. Consider adding a confirmation prompt or using a less destructive alternative for this keymap.

Consider adding a confirmation:

 -- @keymap <leader>bad: Wipe all buffers
-keymap("n", "<leader>bad", ":%bwipeout!<cr>:intro<cr>", opts)
+keymap("n", "<leader>bad", function()
+	if vim.fn.confirm("Wipe all buffers?", "&Yes\n&No", 2) == 1 then
+		vim.cmd("%bwipeout!")
+		vim.cmd("intro")
+	end
+end, opts)

58-74: Terminal functions are called as globals without explicit import, creating an implicit dependency that works by accident.

The review comment is correct. Terminal.lua defines TogglePrimaryTerm(), ToggleSecondaryTerm(), CycleNextTerm(), and CyclePreviousTerm() as global functions (lines 62, 66, 88, 92), but keymaps.lua never requires the terminal module. While the code currently works because these functions are called inside keymap callbacks (executed at runtime, after terminal.lua has been loaded in init.lua), this pattern is fragile and could break if:

  • The loading order in init.lua is changed
  • Code is refactored to call these functions at module load time
  • The module structure changes

The suggested refactoring to use require("terminal") and call functions as module methods is a valid improvement that would eliminate the implicit dependency and make the code more robust.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ef77b29 and f35831e.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (21)
  • flake.nix (1 hunks)
  • home-manager/packages/default.nix (2 hunks)
  • home-manager/programs/neovim/init.lua (1 hunks)
  • home-manager/programs/neovim/lua/ai.lua (1 hunks)
  • home-manager/programs/neovim/lua/autocmds.lua (1 hunks)
  • home-manager/programs/neovim/lua/completion.lua (1 hunks)
  • home-manager/programs/neovim/lua/keymaps.lua (1 hunks)
  • home-manager/programs/neovim/lua/lsp.lua (1 hunks)
  • home-manager/programs/neovim/lua/plugins.lua (1 hunks)
  • home-manager/programs/neovim/lua/settings.lua (1 hunks)
  • home-manager/programs/neovim/lua/telescope.lua (1 hunks)
  • home-manager/programs/neovim/lua/terminal.lua (1 hunks)
  • home-manager/programs/neovim/lua/treesitter.lua (1 hunks)
  • home-manager/programs/neovim/lua/ui.lua (1 hunks)
  • home-manager/programs/neovim/lua/utils.lua (1 hunks)
  • home-manager/programs/neovim/nvim-pack-lock.json (10 hunks)
  • lib/env.nix (1 hunks)
  • nix-darwin/config/dock.nix (1 hunks)
  • nix-darwin/config/homebrew.nix (1 hunks)
  • package.json (1 hunks)
  • treefmt.toml (1 hunks)
🧰 Additional context used
📓 Path-based instructions (10)
**/*.nix

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.nix: Use nixfmt for formatting all Nix files
Document complex configurations with comments in Nix files

**/*.nix: Use 2 spaces for indentation in Nix files
Keep line length under 100 characters in Nix files
Sort attribute sets alphabetically in Nix files
Use consistent spacing around operators in Nix files
Format lists and sets consistently in Nix files

Use treefmt.toml for formatting Nix files

**/*.nix: Use mkOption for configurable options in Nix modules
Implement proper typing for all options in Nix modules
Follow the Nix expression language style guide

Files:

  • nix-darwin/config/homebrew.nix
  • flake.nix
  • lib/env.nix
  • nix-darwin/config/dock.nix
  • home-manager/packages/default.nix
nix-darwin/**/*.nix

📄 CodeRabbit inference engine (CLAUDE.md)

Use Homebrew only for macOS-specific applications

Files:

  • nix-darwin/config/homebrew.nix
  • nix-darwin/config/dock.nix
**/*.{json,yaml,yml,toml}

📄 CodeRabbit inference engine (.cursor/rules/formatting.mdc)

**/*.{json,yaml,yml,toml}: Use consistent indentation (2 spaces) in configuration files
Sort keys alphabetically when possible in configuration files
Use clear, descriptive names in configuration files

Files:

  • treefmt.toml
  • home-manager/programs/neovim/nvim-pack-lock.json
  • package.json
**/*.{yaml,yml,toml}

📄 CodeRabbit inference engine (.cursor/rules/formatting.mdc)

Add comments for complex configurations

Files:

  • treefmt.toml
flake.nix

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

Maintain flake.nix as the main Nix configuration with proper structure

Always pin package versions in flake.lock

Files:

  • flake.nix
**/default.nix

📄 CodeRabbit inference engine (CLAUDE.md)

Use default.nix files for module exports

Files:

  • home-manager/packages/default.nix
home-manager/**/*.nix

📄 CodeRabbit inference engine (.cursor/rules/home-manager.mdc)

home-manager/**/*.nix: Use typed options whenever possible in Nix configurations
Document all configuration options in Nix modules and programs
Follow home-manager's module structure and keep configurations modular
Use proper indentation and formatting in Nix configuration files

Files:

  • home-manager/packages/default.nix
**/*.{js,ts,jsx,tsx,json}

📄 CodeRabbit inference engine (CLAUDE.md)

Use Biome with 2-space indentation, 80-character line width, double quotes, and trailing commas (ES5) for JSON/JavaScript/TypeScript files

Files:

  • home-manager/programs/neovim/nvim-pack-lock.json
  • package.json
**/*.{js,jsx,ts,tsx,json}

📄 CodeRabbit inference engine (.cursor/rules/formatting.mdc)

**/*.{js,jsx,ts,tsx,json}: Format JavaScript/TypeScript/JSON files using Biome with 2-space indentation and 80 character line width
Enable Biome linter with recommended rules for JavaScript/TypeScript/JSON files

Files:

  • home-manager/programs/neovim/nvim-pack-lock.json
  • package.json
**/*.{js,jsx,ts,tsx,json,jsonc,md}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

Use Biome for code formatting as configured in biome.json

Files:

  • home-manager/programs/neovim/nvim-pack-lock.json
  • package.json
🧠 Learnings (15)
📚 Learning: 2025-11-25T09:34:23.224Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T09:34:23.224Z
Learning: Applies to nix-darwin/**/*.nix : Use Homebrew only for macOS-specific applications

Applied to files:

  • nix-darwin/config/homebrew.nix
  • nix-darwin/config/dock.nix
  • home-manager/packages/default.nix
📚 Learning: 2025-11-25T09:34:40.062Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/general.mdc:0-0
Timestamp: 2025-11-25T09:34:40.062Z
Learning: Document all major changes in Nix configurations

Applied to files:

  • nix-darwin/config/homebrew.nix
  • nix-darwin/config/dock.nix
  • home-manager/packages/default.nix
📚 Learning: 2025-11-25T09:34:40.062Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/general.mdc:0-0
Timestamp: 2025-11-25T09:34:40.062Z
Learning: Applies to **/*.nix : Use treefmt.toml for formatting Nix files

Applied to files:

  • treefmt.toml
  • flake.nix
📚 Learning: 2025-11-25T09:34:23.224Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T09:34:23.224Z
Learning: Applies to **/*.{sh,bash} : Use shfmt with 2-space indentation for shell scripts

Applied to files:

  • treefmt.toml
📚 Learning: 2025-11-25T09:34:23.224Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T09:34:23.224Z
Learning: Run `make format` before committing code

Applied to files:

  • treefmt.toml
📚 Learning: 2025-11-25T09:34:23.224Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T09:34:23.224Z
Learning: Applies to **/*.nix : Use nixfmt for formatting all Nix files

Applied to files:

  • treefmt.toml
  • flake.nix
📚 Learning: 2025-11-25T09:34:40.062Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/general.mdc:0-0
Timestamp: 2025-11-25T09:34:40.062Z
Learning: Applies to flake.nix : Maintain flake.nix as the main Nix configuration with proper structure

Applied to files:

  • flake.nix
  • home-manager/packages/default.nix
📚 Learning: 2025-11-25T09:34:55.014Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/home-manager.mdc:0-0
Timestamp: 2025-11-25T09:34:55.014Z
Learning: Applies to home-manager/programs/**/default.nix : Program configurations must include all necessary dependencies in their configuration

Applied to files:

  • home-manager/packages/default.nix
📚 Learning: 2025-11-25T09:34:23.224Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T09:34:23.224Z
Learning: Prefer Nix packages over external package managers

Applied to files:

  • home-manager/packages/default.nix
📚 Learning: 2025-11-25T09:34:55.014Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/home-manager.mdc:0-0
Timestamp: 2025-11-25T09:34:55.014Z
Learning: Applies to home-manager/programs/**/*.nix : Follow program-specific best practices in program configuration files

Applied to files:

  • home-manager/packages/default.nix
📚 Learning: 2025-11-25T09:34:23.224Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T09:34:23.224Z
Learning: Applies to **/default.nix : Use `default.nix` files for module exports

Applied to files:

  • home-manager/packages/default.nix
📚 Learning: 2025-11-25T09:34:40.062Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/general.mdc:0-0
Timestamp: 2025-11-25T09:34:40.062Z
Learning: Applies to **/*.{js,jsx,ts,tsx,json,jsonc,md} : Use Biome for code formatting as configured in biome.json

Applied to files:

  • package.json
📚 Learning: 2025-11-25T09:34:23.224Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T09:34:23.224Z
Learning: Applies to **/*.{js,ts,jsx,tsx,json} : Use Biome with 2-space indentation, 80-character line width, double quotes, and trailing commas (ES5) for JSON/JavaScript/TypeScript files

Applied to files:

  • package.json
📚 Learning: 2025-11-25T09:34:32.423Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/formatting.mdc:0-0
Timestamp: 2025-11-25T09:34:32.423Z
Learning: Applies to **/*.{js,jsx,ts,tsx,json} : Enable Biome linter with recommended rules for JavaScript/TypeScript/JSON files

Applied to files:

  • package.json
📚 Learning: 2025-11-25T09:34:32.423Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/formatting.mdc:0-0
Timestamp: 2025-11-25T09:34:32.423Z
Learning: Applies to **/*.{js,jsx,ts,tsx,json} : Format JavaScript/TypeScript/JSON files using Biome with 2-space indentation and 80 character line width

Applied to files:

  • package.json
🧬 Code graph analysis (1)
home-manager/programs/neovim/lua/keymaps.lua (1)
home-manager/programs/neovim/lua/terminal.lua (4)
  • TogglePrimaryTerm (62-64)
  • ToggleSecondaryTerm (66-68)
  • CycleNextTerm (88-90)
  • CyclePreviousTerm (92-94)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: Agent
  • GitHub Check: Cursor Bugbot
  • GitHub Check: lua-neovim
  • GitHub Check: lua-hammerspoon
  • GitHub Check: nix-nixos
  • GitHub Check: nix-linux
  • GitHub Check: nix-darwin
  • GitHub Check: docker-build-push (linux/amd64, amd64, ubuntu-latest)
  • GitHub Check: docker-build-push (linux/arm64, arm64, ubuntu-24.04-arm)
  • GitHub Check: e2e-run (MacOS, macos-latest)
  • GitHub Check: e2e-run (NixOS, ubuntu-latest)
  • GitHub Check: e2e-run (Ubuntu, ubuntu-latest)
🔇 Additional comments (27)
package.json (2)

14-22: Dependencies include pre-release and alpha versions.

The new dependencies include pre-release versions:

  • @getgrit/cli at ^0.1.0-alpha.1743007075 (alpha)
  • @typescript/native-preview at ^7.0.0-dev.20251127.1 (dev preview)

These are acceptable for a dotfiles repository but may introduce breaking changes. Ensure you're prepared to handle potential API instability.


24-34: trustedDependencies correctly updated.

All newly added dependencies are appropriately included in trustedDependencies, ensuring they can execute lifecycle scripts.

nix-darwin/config/dock.nix (1)

31-34: LGTM!

The new dock entries for Tailscale and VS Code Insiders are correctly positioned alongside related applications, and they align with the corresponding Homebrew cask additions in homebrew.nix.

home-manager/programs/neovim/lua/utils.lua (3)

3-90: Buffer cycling implementation is well-structured.

The cycle_buffer function handles edge cases properly with valid buffer checks, deduplication, and wrapping logic. Minor note: line 30 (buffer_set[current_buf] = true) is technically redundant since buffer_set isn't used after this point, but it's harmless and maintains consistency.


92-98: Verify intended behavior for single-item quickfix lists.

The condition size > 1 means the quickfix window opens only when there are 2+ items. A single-item list will close the quickfix window. If you intend to show the quickfix for any non-empty list, consider:

 function M.copen()
-	if vim.fn.getqflist({ size = 0 }).size > 1 then
+	if vim.fn.getqflist({ size = 0 }).size > 0 then
 		vim.cmd("copen")
 	else
 		vim.cmd("cclose")
 	end
 end

If hiding single-item lists is intentional (e.g., for cleaner UX when there's only one result), the current logic is fine.


100-104: LGTM!

The cclear function correctly uses setqflist with the "r" action to replace and clear the quickfix list.

home-manager/programs/neovim/lua/ai.lua (1)

1-3: Perfect! I've completed the verification. Let me summarize my findings:

Verification Results:

  • ✅ sidekick.nvim IS declared as a dependency in plugins.lua (line 79, under AI category)
  • ✅ ai.lua IS properly required in init.lua (line 40)
  • ✅ Loading order is correct: plugins are loaded (line 33) before ai module (line 40)
  • ✅ The empty config {} is valid and appropriate

The original review's concern about verifying the plugin installation is unnecessary—the plugin is already properly configured. Additionally, the original review contains non-standard tags that should be removed.


LGTM!

The sidekick.nvim setup is correctly configured. The plugin is properly declared as a dependency in plugins.lua (line 79), and ai.lua is loaded in init.lua after plugins are initialized. The empty options table uses sensible defaults.

home-manager/programs/neovim/nvim-pack-lock.json (1)

1-257: Lock file additions look good.

The new plugin entries are well-structured with consistent rev and src fields. Keys are alphabetically sorted as expected. The plugins align with the modular Neovim configuration changes in this PR.

treefmt.toml (1)

20-23: Stylua formatter addition looks good.

The Lua formatter entry follows the established pattern. Consider adding explicit options for consistency with the Neovim config's indentation style (tabs vs spaces):

 [formatter.lua]
 command = "stylua"
+options = ["--indent-type", "Tabs"]
 includes = ["*.lua"]

This is optional since stylua can also read from a .stylua.toml if present. Based on learnings, treefmt.toml is the expected location for formatting configuration.

lib/env.nix (1)

1-3: Environment detection module is functional.

The builtins.getEnv usage is appropriate for CI detection. Note that this makes the expression impure—evaluations will differ based on environment variables at eval time. This is expected and necessary for conditional package inclusion.

Consider documenting the expected environment variables:

 {
+  # CI detection: true when running in CI or Docker environments
+  # Set CI=1 or IN_DOCKER=true to enable
   isCI = builtins.getEnv "CI" != "" || builtins.getEnv "IN_DOCKER" == "true";
 }
home-manager/programs/neovim/lua/telescope.lua (1)

42-44: Extension loading order is correct.

The gh extension requires telescope-github.nvim which is present in the lock file. Good practice loading extensions after setup.

home-manager/packages/default.nix (2)

1-3: Clean import pattern for environment detection.

The use of inherit to destructure isCI from the imported module is idiomatic Nix. This centralizes CI detection logic in lib/env.nix for reuse across the codebase.


92-98: Good separation of CI-excluded packages.

Heavy GUI applications like chromium, github-desktop, signal-desktop, and vlc are appropriately excluded from CI builds to reduce build times and avoid unnecessary downloads. This is a sensible optimization.

flake.nix (1)

170-172: Lua formatter configuration is correct—no conflicts or duplication.

The review comment incorrectly flagged a potential conflict. Here's why there is none:

  • treefmt.toml defines the base lua formatter configuration (command: "stylua", includes: "*.lua")
  • flake.nix treefmtSettings overrides the command to use the Nix-wrapped executable (lib.getExe pkgs.stylua)
  • treefmt.programs.stylua.enable enables stylua in the devenv integration layer

This is the correct architecture: the base config lives in treefmt.toml, the Nix package override happens in flake.nix, and the devenv enablement is separate. All formatters (nix, biome, json, shell, lua) follow this identical pattern. No duplication or conflict exists.

home-manager/programs/neovim/init.lua (2)

10-14: LGTM! Clean helper for extending package.path.

The duplicate check with string.find(..., 1, true) using plain matching is correct and prevents redundant path entries.


32-43: Module loading order looks intentional and correct.

Settings before plugins ensures vim options are configured before plugins initialize. The dependency chain (settings → plugins → autocmds → keymaps → lsp → etc.) is logical.

home-manager/programs/neovim/lua/settings.lua (1)

26-31: LGTM! Directory creation with proper error handling.

Using "p" flag for mkdir correctly creates parent directories as needed and doesn't error if the directory already exists.

home-manager/programs/neovim/lua/ui.lua (3)

14-41: LGTM! Dynamic theme configuration for lualine.

The theme function and lualine configuration are well-structured with proper section organization.


95-101: Multiple keys mapped to the same action (horizontal split).

Both s (line 97) and i (line 101) are mapped to api.node.open.horizontal. If intentional, this is fine for muscle-memory compatibility; otherwise, consider removing the duplicate.


149-163: LGTM! Clean plugin initialization.

The remaining plugin setups with empty configs are appropriate for using plugin defaults. Good use of comments documenting the purpose and source of each plugin.

home-manager/programs/neovim/lua/plugins.lua (2)

94-94: AI summary inconsistency detected.

The AI-generated summary mentions formatters like "prettier" and "ruff", but the actual code uses "biome" for JavaScript/TypeScript and "black" for Python. The code takes precedence.


30-30: make is already included as a managed dependency via gnumake in home-manager packages and installed by install.sh.

The telescope-fzf-native plugin does require make to build from source. However, this dependency is already handled by the repository's build system:

  • install.sh (lines 28–36) explicitly checks for and installs make if not present
  • home-manager/packages/default.nix includes gnumake as a managed package
  • The plugin build executes in an environment where this dependency is available

No action needed—the build dependency is properly managed.

home-manager/programs/neovim/lua/treesitter.lua (2)

1-27: LGTM!

The plugin configurations are clean and well-documented with source URLs. Using default configurations is appropriate for these plugins, as they work well out of the box.


110-162: LGTM!

The textobjects configuration is comprehensive and follows Vim conventions. The keymaps for swapping, moving, and selecting code structures are well-organized and shouldn't conflict with standard Vim keybindings.

home-manager/programs/neovim/lua/keymaps.lua (3)

1-11: LGTM!

The keymap setup is clean and well-structured. The Space leader key is a good choice, and the opts table with noremap and silent defaults will prevent mapping recursion and suppress command-line messages.


77-152: LGTM!

These keymap sections are well-organized and follow Neovim best practices:

  • Navigation keymaps with centering improve UX
  • Flash integration is clean
  • Git operations properly leverage vim-fugitive and gitsigns
  • Visual mode operations enhance workflow
  • Insert mode undo breakpoints after punctuation are a nice productivity touch

155-224: LGTM!

The diagnostics and code operations sections are comprehensive:

  • Trouble integration provides multiple entry points for different diagnostic views
  • Code navigation keymaps (Oil, GrugFar, other.nvim, Neogen) are well-organized
  • Treesj setup and usage are clean
  • Which-key group definitions will provide helpful hints to users

Comment on lines +47 to +53
cmp.setup.filetype("gitcommit", {
sources = cmp.config.sources({
{ name = "git" }, -- You can specify the `git` source if you have it configured
}, {
{ name = "buffer" },
}),
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for lock file and cmp-git references
echo "=== Searching for lock files ==="
find . -name "*lock*" -type f | head -20

echo ""
echo "=== Searching for cmp-git in the repo ==="
rg -i "cmp-git|petertriho" --type=json --type=nix --type=yaml -n

Repository: shunkakinoki/dotfiles

Length of output: 215


🏁 Script executed:

#!/bin/bash
# Check the nvim-pack-lock.json file
echo "=== Checking nvim-pack-lock.json file size ==="
wc -l ./home-manager/programs/neovim/nvim-pack-lock.json

echo ""
echo "=== Searching for 'git' in the lock file ==="
rg -i "git" ./home-manager/programs/neovim/nvim-pack-lock.json -n

echo ""
echo "=== Listing all plugins in lock file ==="
rg '"repo"' ./home-manager/programs/neovim/nvim-pack-lock.json -n | head -30

Repository: shunkakinoki/dotfiles

Length of output: 4245


🏁 Script executed:

#!/bin/bash
# Read the completion.lua file to verify the configuration
echo "=== Reading completion.lua ==="
cat -n ./home-manager/programs/neovim/lua/completion.lua

Repository: shunkakinoki/dotfiles

Length of output: 2956


🏁 Script executed:

#!/bin/bash
# Search web for cmp-git plugin and nvim-cmp missing source handling
echo "=== Checking cmp-git plugin ==="
rg -i "petertriho/cmp-git" . 2>/dev/null || echo "No references found"

echo ""
echo "=== Checking if there's any documentation about missing sources ==="
fd "README*" ./home-manager/programs/neovim --type f | head -5

Repository: shunkakinoki/dotfiles

Length of output: 185


Based on my verification, the review comment is accurate and identifies a real issue. Here's what I confirmed:

Verification Results:

  • cmp-git plugin is NOT in nvim-pack-lock.json (checked 256-line file, found no petertriho/cmp-git)
  • completion.lua line 49 references { name = "git" } source unconditionally
  • ✅ The comment on line 49 acknowledges the source is optional ("if you have it configured"), but this doesn't prevent the configuration from being loaded
  • ✅ No error handling exists for missing sources; nvim-cmp will fail when trying to initialize a non-existent source provider

The issue is legitimate: the configuration attempts to use a completion source (cmp-git) that is not installed. While there's a fallback to the buffer source, the git source entry itself will cause errors during initialization.


Missing cmp-git plugin.

The { name = "git" } source on line 49 requires the cmp-git plugin, which is not installed in your setup (verified in nvim-pack-lock.json). This will cause completion source initialization to fail for gitcommit buffers.

Either install cmp-git or remove this source from the configuration:

 cmp.setup.filetype("gitcommit", {
 	sources = cmp.config.sources({
-		{ name = "git" }, -- You can specify the `git` source if you have it configured
-	}, {
 		{ name = "buffer" },
 	}),
 })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
cmp.setup.filetype("gitcommit", {
sources = cmp.config.sources({
{ name = "git" }, -- You can specify the `git` source if you have it configured
}, {
{ name = "buffer" },
}),
})
cmp.setup.filetype("gitcommit", {
sources = cmp.config.sources({
{ name = "buffer" },
}),
})
🤖 Prompt for AI Agents
In home-manager/programs/neovim/lua/completion.lua around lines 47 to 53, the
cmp configuration unconditionally includes the { name = "git" } source which
requires the cmp-git plugin (not present in nvim-pack-lock.json) and will cause
nvim-cmp to fail; fix by either adding cmp-git to your plugin list
(nvim-pack-lock.json / plugin manager) or remove the { name = "git" } entry from
the cmp.setup.filetype("gitcommit", ...) block, or guard its inclusion with a
runtime check (e.g., pcall(require, "cmp_git") or a boolean flag) so the git
source is only registered when the plugin is installed.

Comment on lines +40 to +45
for name, config in pairs(servers) do
config.on_attach = on_attach
config.capabilities = capabilities
vim.lsp.config(name, config)
end
vim.lsp.enable(vim.tbl_keys(servers))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

Neovim vim.lsp.config vim.lsp.enable API version 0.11 introduction

💡 Result:

Short summary — what changed in v0.11

  • Neovim 0.11 introduced a built-in LSP configuration API: vim.lsp.config and vim.lsp.enable. Use vim.lsp.config(...) to define or modify server configs and vim.lsp.enable(...) to auto-start/stop those configs for matching buffers. [1]

  • Purpose: unify/centralize LSP config into core (less boilerplate), allow plugins (and your local lsp/*.lua) to provide configs that are merged with user overrides, and replace the old programmatic setup API used by require('lspconfig').setup(...). [1][2]

  • Migration notes: nvim-lspconfig now provides server configs under an lsp/ directory consumed by vim.lsp.config; the old require('lspconfig') "framework"/setup API is deprecated and users are encouraged to migrate to vim.lsp.config + vim.lsp.enable (and use LspAttach for on_attach behavior). See the project migration issue/README for details and examples. [2][3]

Quick example

  • Define defaults or a server:
    vim.lsp.config('clangd', { cmd = {'clangd'}, filetypes = {'c','cpp'} })
  • Enable it (auto-starts on matching filetypes/root):
    vim.lsp.enable('clangd')
    (You can pass a list to vim.lsp.enable and pass false to disable.) [1]

Sources
[1] Neovim LSP docs (:help lsp) — vim.lsp.config / vim.lsp.enable (Since: 0.11.0).
[2] nvim-lspconfig README / migration notes (migration to vim.lsp.config).
[3] nvim-lspconfig GitHub discussion/issue about migrating to vim.lsp.config.


🏁 Script executed:

#!/bin/bash
# Find Neovim version requirements in the repository
echo "=== Searching for Neovim version requirements ==="
find . -type f \( -name "*.md" -o -name "*.nix" -o -name "*.lua" -o -name "*.toml" -o -name "*.json" \) | head -20 | xargs grep -l "neovim" 2>/dev/null | head -10

echo ""
echo "=== Checking file location and size ==="
wc -l home-manager/programs/neovim/lua/lsp.lua 2>/dev/null || echo "File not found, searching..."
find . -name "lsp.lua" -type f 2>/dev/null

Repository: shunkakinoki/dotfiles

Length of output: 242


🏁 Script executed:

#!/bin/bash
# Read the full lsp.lua file
echo "=== Full lsp.lua file ==="
cat -n home-manager/programs/neovim/lua/lsp.lua

echo ""
echo "=== Searching for Neovim version specifications ==="
# Search for version constraints in common config files
find . -type f \( -name "*.nix" -o -name "flake.lock" -o -name "init.lua" -o -name "*.json" \) | xargs grep -i "neovim\|nvim" 2>/dev/null | grep -i "version\|0\.[0-9]\|unstable" | head -20

Repository: shunkakinoki/dotfiles

Length of output: 2559


🏁 Script executed:

#!/bin/bash
echo "=== Searching for Neovim in nix files ==="
find . -name "*.nix" -type f | head -20 | xargs grep -A3 -B3 "neovim\|nvim" 2>/dev/null | head -50

echo ""
echo "=== Looking for flake.nix or default.nix ==="
find . -name "flake.nix" -o -name "default.nix" 2>/dev/null | head -5

echo ""
echo "=== Searching in README files ==="
find . -name "README*" -type f | xargs grep -i "neovim\|nvim" 2>/dev/null | head -10

Repository: shunkakinoki/dotfiles

Length of output: 564


Based on my verification, I can now provide the rewritten review comment:

Add Neovim 0.11+ version requirement or implement version guard for LSP configuration APIs.

The vim.lsp.config and vim.lsp.enable functions were introduced in Neovim 0.11.0. Your code uses these APIs without a version guard, but the project's devenv.nix uses pkgs.neovim without pinning a specific version. Either add an explicit Neovim 0.11+ version constraint to your nix configuration or add a runtime version check (e.g., vim.fn.has('nvim-0.11')) to gracefully handle earlier versions.

	for name, config in pairs(servers) do
		config.on_attach = on_attach
		config.capabilities = capabilities
		vim.lsp.config(name, config)
	end
	vim.lsp.enable(vim.tbl_keys(servers))
🤖 Prompt for AI Agents
In home-manager/programs/neovim/lua/lsp.lua around lines 40 to 45, the code
calls vim.lsp.config and vim.lsp.enable which only exist in Neovim 0.11+, so add
a version guard or require a 0.11+ pin: either (A) add a runtime check using
vim.fn.has('nvim-0.11') and only run the vim.lsp.* block when true (otherwise
fall back to the older lspconfig setup for each server or skip), or (B) enforce
Neovim >= 0.11 in the Nix config by pinning pkgs.neovim to a 0.11+ release;
implement one of these fixes and ensure the fallback path configures servers via
require('lspconfig')[name].setup with on_attach and capabilities when the
runtime check fails.

Comment on lines +94 to +114
require("conform").setup({
formatters_by_ft = {
lua = { "stylua" },
python = { "black" },
javascript = { "biome" },
typescript = { "biome" },
javascriptreact = { "biome" },
typescriptreact = { "biome" },
json = { "biome" },
yaml = { "biome" },
markdown = { "biome" },
html = { "biome" },
css = { "biome" },
go = { "gofmt", "goimports" },
nix = { "nixfmt" },
},
format_on_save = {
timeout_ms = 500,
lsp_fallback = true,
},
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, check the repository structure to understand the context
echo "=== Repository Structure ==="
git ls-files | head -20
echo ""
echo "=== Checking for nix configuration ==="
find . -name "*.nix" -type f | head -20

Repository: shunkakinoki/dotfiles

Length of output: 1201


🏁 Script executed:

#!/bin/bash
# Find neovim configuration in home-manager
echo "=== Finding neovim configuration ==="
find home-manager/programs -name "*neovim*" -o -name "*nvim*" | head -20
echo ""
echo "=== Checking the specific plugins.lua file ==="
find . -path "*neovim/lua/plugins.lua" -o -path "*nvim/lua/plugins.lua"
echo ""
echo "=== Checking devenv.nix ==="
wc -l devenv.nix

Repository: shunkakinoki/dotfiles

Length of output: 317


🏁 Script executed:

#!/bin/bash
# Read the plugins.lua file
echo "=== Reading plugins.lua ==="
cat -n home-manager/programs/neovim/lua/plugins.lua
echo ""
echo "=== Reading devenv.nix ==="
cat -n devenv.nix
echo ""
echo "=== Finding home-manager neovim configuration ==="
find home-manager/programs/neovim -name "*.nix"

Repository: shunkakinoki/dotfiles

Length of output: 6211


🏁 Script executed:

#!/bin/bash
# Read the neovim home-manager configuration
echo "=== Reading home-manager/programs/neovim/default.nix ==="
cat -n home-manager/programs/neovim/default.nix

Repository: shunkakinoki/dotfiles

Length of output: 1009


🏁 Script executed:

#!/bin/bash
# Search for formatter declarations across home-manager
echo "=== Searching for stylua in home-manager ==="
rg -n "stylua" home-manager/ 2>/dev/null || echo "Not found"
echo ""
echo "=== Searching for black in home-manager ==="
rg -n "black" home-manager/ 2>/dev/null || echo "Not found"
echo ""
echo "=== Searching for biome in home-manager ==="
rg -n "biome" home-manager/ 2>/dev/null || echo "Not found"
echo ""
echo "=== Searching for goimports in home-manager ==="
rg -n "goimports" home-manager/ 2>/dev/null || echo "Not found"
echo ""
echo "=== Searching for nixfmt in home-manager ==="
rg -n "nixfmt" home-manager/ 2>/dev/null || echo "Not found"

Repository: shunkakinoki/dotfiles

Length of output: 1363


🏁 Script executed:

#!/bin/bash
# Check home-manager/default.nix
echo "=== Reading home-manager/default.nix ==="
wc -l home-manager/default.nix
head -100 home-manager/default.nix
echo ""
echo "=== Reading home-manager/packages/default.nix ==="
wc -l home-manager/packages/default.nix

Repository: shunkakinoki/dotfiles

Length of output: 1089


🏁 Script executed:

#!/bin/bash
# Read the full packages/default.nix
echo "=== Reading home-manager/packages/default.nix ==="
cat -n home-manager/packages/default.nix

Repository: shunkakinoki/dotfiles

Length of output: 1951


🏁 Script executed:

#!/bin/bash
# Search for extraPackages in neovim config
echo "=== Searching for extraPackages in neovim ==="
rg -n "extraPackages" home-manager/programs/neovim/ 2>/dev/null || echo "Not found"
echo ""
# Check for flake.nix
echo "=== Checking for flake.nix ==="
find . -name "flake.nix" -type f
echo ""
# Check for any documentation about formatters or setup
echo "=== Checking README and FAQ ==="
ls -la *.md

Repository: shunkakinoki/dotfiles

Length of output: 497


🏁 Script executed:

#!/bin/bash
# Check flake.nix for formatter declarations
echo "=== Reading flake.nix ==="
wc -l flake.nix
head -150 flake.nix
echo ""
# Check README and documentation
echo "=== Reading README.md ==="
cat README.md
echo ""
echo "=== Reading FAQ.md ==="
cat FAQ.md

Repository: shunkakinoki/dotfiles

Length of output: 5929


🏁 Script executed:

#!/bin/bash
# Read the rest of flake.nix
echo "=== Reading rest of flake.nix (lines 150-198) ==="
tail -50 flake.nix
echo ""
# Check for treefmt.nix
echo "=== Checking for treefmt.nix ==="
find . -name "treefmt.nix" -type f
echo ""
# Search for formatter configurations in flake.nix
echo "=== Searching for treefmt configuration in flake.nix ==="
rg -n "treefmt" flake.nix

Repository: shunkakinoki/dotfiles

Length of output: 2665


🏁 Script executed:

#!/bin/bash
# Read treefmt.toml
echo "=== Reading treefmt.toml ==="
cat -n treefmt.toml
echo ""
# Search for black, gofmt, goimports in entire repo
echo "=== Searching for go package declarations ==="
rg -n "pkgs\.go\b|pkgs\.python" flake.nix home-manager/
echo ""
# List all formatters mentioned in treefmt and compare with conform
echo "=== Summary of available vs configured formatters ==="
echo "Formatters in conform.nvim config:"
echo "  - stylua (lua)"
echo "  - black (python)"
echo "  - biome (javascript, typescript, json, yaml, markdown, html, css)"
echo "  - gofmt, goimports (go)"
echo "  - nixfmt (nix)"
echo ""
echo "Formatters available in treefmt:"
rg "command = lib.getExe pkgs\." flake.nix | sed 's/.*pkgs\.\([^ ;]*\).*/  - \1/'

Repository: shunkakinoki/dotfiles

Length of output: 151


🏁 Script executed:

#!/bin/bash
# Read treefmt.toml
echo "=== Reading treefmt.toml ==="
cat treefmt.toml

Repository: shunkakinoki/dotfiles

Length of output: 558


Some configured formatters are missing from the nix environment, which will cause format_on_save to fail for affected file types.

The conform.nvim setup references six formatters, but only three are provisioned in the nix environment:

Available (via treefmt): stylua, biome, nixfmt
Missing: black (Python), gofmt, goimports (Go)

When format_on_save is triggered on Python or Go files, conform will fail to find these tools and fall back to LSP, potentially degrading the formatting experience. Consider either:

  • Adding missing formatters to home-manager/packages/default.nix: black, go (includes gofmt and goimports), or
  • Removing them from the conform configuration if they're not needed
🤖 Prompt for AI Agents
In home-manager/programs/neovim/lua/plugins.lua around lines 94 to 114, the
conform.nvim config references formatters (black, gofmt, goimports) that are not
provided by the nix environment which will cause format_on_save to fail for
Python and Go; either add those binaries to the nix profile (e.g., add black and
go to home-manager/packages/default.nix) or remove those formatters from
formatters_by_ft so conform only lists tools actually available (ensure changes
are mirrored in the nix expression and rebuild the environment).

Comment on lines +119 to +130
local lint = require("lint")
lint.linters_by_ft = {
python = { "pylint" },
javascript = { "eslint" },
typescript = { "eslint" },
}

vim.api.nvim_create_autocmd({ "BufWritePost" }, {
callback = function()
lint.try_lint()
end,
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, let's understand the repository structure and find related files
echo "=== Repository structure ==="
find . -type f -name "*.lua" -o -name "*.nix" | head -20

echo ""
echo "=== Searching for nvim-lint or lint references ==="
rg -i "nvim-lint|lint" --type lua --type nix -A 2 -B 2 | head -50

Repository: shunkakinoki/dotfiles

Length of output: 2107


🏁 Script executed:

#!/bin/bash
# Check the actual file in question
echo "=== Content of plugins.lua around lines 119-130 ==="
if [ -f "home-manager/programs/neovim/lua/plugins.lua" ]; then
    sed -n '100,140p' "home-manager/programs/neovim/lua/plugins.lua"
else
    echo "File not found, searching for plugins.lua..."
    fd "plugins.lua" -e lua
fi

Repository: shunkakinoki/dotfiles

Length of output: 747


🌐 Web query:

nvim-lint try_lint missing linters error handling

💡 Result:

Summary — what's happening

  • require("lint").try_lint() uses the linters listed in lint.linters_by_ft for the current filetype (or any explicit linter names you pass). If a configured linter's executable or output differs (writes to stderr, returns non‑zero exit code, or prints plain error text when no config/exec is found), nvim-lint will still run the linter and then try to parse its output — which can produce "Could not parse linter output..." or similar messages. [1][2]

How to diagnose & fix

  1. Confirm which linters are being run

    • Check your lint.linters_by_ft and call try_lint with explicit names to isolate: require('lint').try_lint('eslint_d') or require('lint').try_lint({'eslint_d','other'}). (try_lint() with no args runs linters_by_ft for the buffer.) [1]
  2. Ensure the linter executable is found

    • Either install the linter in the project, make sure the global exe is on PATH accessible to Neovim, or set your linter's cmd to a full path in require('lint').linters..cmd. Many "missing" errors come from the executable not being found. [1][2]
  3. Handle linters that print errors to stderr or exit non‑zero

    • Configure the linter entry:
      • stream = 'stderr' (or 'both') if the tool writes to stderr.
      • ignore_exitcode = true if the linter uses non‑zero exit codes for normal cases.
      • add a custom parser (linters..parser) to ignore or transform human error messages (e.g., "No ESLint found" or "No ESLint configuration found") so they don’t cause a parse failure. [1][2]
  4. Example (Lua)

    • Minimal ideas (adapt to your linter):
      • set full cmd path: require('lint').linters.eslint_d.cmd = '/usr/local/bin/eslint_d'
      • tell plugin to read stderr: require('lint').linters.eslint_d.stream = 'stderr'
      • ignore exit code: require('lint').linters.eslint_d.ignore_exitcode = true
      • add parser to filter messages (implement parser to return empty table when output contains "No ESLint configuration"). See custom linter docs in README. [1]

Known issues & context

  • There are existing issues where eslint_d or other linters produce plain error text (or a missing config) and the built‑in parser fails to parse it; people have reported that ignore_errors/ignore_exitcode alone may not be sufficient and a custom parser or ensuring the correct executable/config is required. See issue discussion for eslint_d examples. [2]

References

  • nvim-lint README / linters and custom linter fields (cmd, stream, ignore_exitcode, parser, linters_by_ft, try_lint usage). [1]
  • GitHub issue examples showing parse failures when linter prints human error messages (eslint_d / "No ESLint configuration found"). [2]

If you want, paste your linters_by_ft plus the specific linter config and the exact error output you see and I’ll give the exact config or a parser function to swallow that message.


🏁 Script executed:

#!/bin/bash
# Check for any error handling or pcall around lint operations
echo "=== Searching for error handling in lint configuration ==="
rg -i "pcall|try|catch|error" -A 3 -B 3 "lint" --type lua

echo ""
echo "=== Full lint configuration block ==="
sed -n '119,150p' "home-manager/programs/neovim/lua/plugins.lua"

Repository: shunkakinoki/dotfiles

Length of output: 459


🏁 Script executed:

#!/bin/bash
# Check for any installation or setup documentation
echo "=== Searching for dependency documentation ==="
fd -e nix -e md | xargs grep -l "pylint\|eslint" | head -10

echo ""
echo "=== Check home-manager neovim configuration ==="
find home-manager/programs/neovim -type f | head -20

Repository: shunkakinoki/dotfiles

Length of output: 877


🏁 Script executed:

#!/bin/bash
# Check the neovim nix configuration for linter dependencies
echo "=== Checking default.nix for linter dependencies ==="
cat home-manager/programs/neovim/default.nix | head -100

echo ""
echo "=== Searching for pylint/eslint in nix files ==="
rg "pylint|eslint" --type nix home-manager/programs/neovim/

Repository: shunkakinoki/dotfiles

Length of output: 151


Based on my verification, I have enough evidence to rewrite the review comment. The web search confirmed that nvim-lint's try_lint() method requires the configured linter executables to be available in PATH and will produce errors if they are missing. The code contains no error handling around the callback.


Ensure configured linters (pylint, eslint) are available in the environment or wrap the lint call in error handling.

The linting setup calls lint.try_lint() on every BufWritePost without error handling. If pylint or eslint are not installed or not in PATH, this will produce errors on every file save. Either ensure these linters are available as dependencies in your environment, or wrap the callback with pcall() to suppress errors gracefully:

vim.api.nvim_create_autocmd({ "BufWritePost" }, {
	callback = function()
		pcall(function() lint.try_lint() end)
	end,
})

vim.opt.termguicolors = true
vim.opt.shortmess:append("c")
vim.opt.timeoutlen = 300
vim.opt.winborder = "none"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

Neovim winborder option availability version

💡 Result:

The global 'winborder' option was added for Neovim 0.11 (via PR neovim/neovim#31074). See the options docs and related issue referencing the 0.11 change. [1][2]

Sources:


🏁 Script executed:

#!/bin/bash
# Search for Neovim version specifications in the repository
find . -type f \( -name "*.md" -o -name "*.nix" -o -name "*.lua" -o -name "*.json" -o -name "*.toml" \) | head -20

Repository: shunkakinoki/dotfiles

Length of output: 531


🏁 Script executed:

#!/bin/bash
# Look for version requirements in README or main config files
rg -i "neovim.*version|minimum.*neovim|nvim.*require" -C 2 | head -50

Repository: shunkakinoki/dotfiles

Length of output: 47


🏁 Script executed:

#!/bin/bash
# Check for any version specifications in the neovim settings file and nearby files
fd -e nix -e lua -e md . home-manager/programs/neovim/ 2>/dev/null | head -20

Repository: shunkakinoki/dotfiles

Length of output: 678


🏁 Script executed:

#!/bin/bash
# Check the neovim default.nix for version specifications
cat -n home-manager/programs/neovim/default.nix | head -100

Repository: shunkakinoki/dotfiles

Length of output: 952


🏁 Script executed:

#!/bin/bash
# Check README and documentation for Neovim version requirements
rg -i "neovim.*version|minimum.*version|0\.[0-9]+" README* 2>/dev/null | head -20

Repository: shunkakinoki/dotfiles

Length of output: 47


🏁 Script executed:

#!/bin/bash
# Check settings.lua for any version-related comments
cat -n home-manager/programs/neovim/lua/settings.lua | grep -i "version\|winborder" -B 2 -A 2

Repository: shunkakinoki/dotfiles

Length of output: 278


Document minimum Neovim version requirement or add version check for winborder option.

vim.opt.winborder was added in Neovim 0.11. The configuration uses pkgs.neovim without a pinned version, which typically resolves to the latest stable release. However, if you support users with older Neovim versions, this setting will cause an error. Either document the minimum Neovim 0.11+ requirement in your README or add a version guard:

if vim.fn.has("nvim-0.11") == 1 then
  vim.opt.winborder = "none"
end
🤖 Prompt for AI Agents
In home-manager/programs/neovim/lua/settings.lua around line 49, the config sets
vim.opt.winborder which only exists in Neovim 0.11+, so add a version guard or
document the minimum version; fix by wrapping the assignment in a check using
vim.fn.has("nvim-0.11") == 1 before setting vim.opt.winborder, or alternatively
update README to explicitly require Neovim 0.11+ so users with older versions
won't hit an error.

scope_incremental = "<noop>",
},
},
auto_install = true,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Consider the implications of auto_install = true in CI/restricted environments.

The auto_install setting will automatically install missing Treesitter parsers when opening files. This might cause issues in CI environments, read-only filesystems, or air-gapped systems. Based on learnings, you may want to conditionally disable this in CI.

Consider checking if the isCI variable from lib/env.nix is available and conditionally setting this:

-- Conditionally set auto_install based on environment
auto_install = not vim.env.IS_CI,

Or explicitly set it to false if you prefer manual parser management in your Nix-based setup.

🤖 Prompt for AI Agents
In home-manager/programs/neovim/lua/treesitter.lua around line 109, auto_install
is set to true which will attempt to download/install parsers at runtime and can
fail in CI, read-only or air-gapped environments; change this to be conditional
on the environment (disable in CI) or explicitly false. Modify the assignment to
consult an environment flag (e.g., vim.env.IS_CI or a value exported from
lib/env.nix) and set auto_install = not vim.env.IS_CI (or auto_install = false)
so parsers are not installed automatically in restricted environments.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (2)
home-manager/programs/neovim/init.lua (2)

16-27: Consider removing redundant package.path setup.

A previous reviewer noted that lines 16-18 are likely redundant with lines 20-27, since both should point to the same configuration directory in typical setups. The dynamic resolution (lines 20-27) is more robust as it resolves symlinks, making the earlier setup unnecessary.

Apply this diff to remove the redundancy:

-local config_lua_path = vim.fn.stdpath("config") .. "/lua/?.lua"
-append_package_path(config_lua_path)
-append_package_path(vim.fn.stdpath("config") .. "/lua/?/init.lua")
-
 local init_source = debug.getinfo(1, "S").source

43-43: Consider removing redundant utils require.

A previous reviewer noted that utils is not used in init.lua itself and is already properly required in keymaps.lua where it's actually needed (for utils.cycle_buffer()). Unless the utils module has initialization side effects that should run at startup, this line can be removed.

Apply this diff if the utils module has no critical initialization side effects:

 require("terminal")
 require("ui")
-require("utils")
 require("workspace")
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f35831e and f91c8cb.

📒 Files selected for processing (4)
  • home-manager/programs/neovim/init.lua (1 hunks)
  • home-manager/programs/neovim/lua/workspace.lua (1 hunks)
  • nix-darwin/config/dock.nix (1 hunks)
  • nix-darwin/config/homebrew.nix (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • nix-darwin/config/dock.nix
🧰 Additional context used
📓 Path-based instructions (2)
**/*.nix

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.nix: Use nixfmt for formatting all Nix files
Document complex configurations with comments in Nix files

**/*.nix: Use 2 spaces for indentation in Nix files
Keep line length under 100 characters in Nix files
Sort attribute sets alphabetically in Nix files
Use consistent spacing around operators in Nix files
Format lists and sets consistently in Nix files

Use treefmt.toml for formatting Nix files

**/*.nix: Use mkOption for configurable options in Nix modules
Implement proper typing for all options in Nix modules
Follow the Nix expression language style guide

Files:

  • nix-darwin/config/homebrew.nix
nix-darwin/**/*.nix

📄 CodeRabbit inference engine (CLAUDE.md)

Use Homebrew only for macOS-specific applications

Files:

  • nix-darwin/config/homebrew.nix
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/general.mdc:0-0
Timestamp: 2025-11-25T09:34:40.062Z
Learning: Applies to **/*.nix : Use treefmt.toml for formatting Nix files
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/general.mdc:0-0
Timestamp: 2025-11-25T09:34:40.062Z
Learning: Keep configurations modular across home-manager, hosts, and nix-darwin directories
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T09:34:23.224Z
Learning: Applies to **/*.nix : Use nixfmt for formatting all Nix files
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/home-manager.mdc:0-0
Timestamp: 2025-11-25T09:34:55.014Z
Learning: Applies to home-manager/**/*.nix : Follow home-manager's module structure and keep configurations modular
📚 Learning: 2025-11-25T09:34:23.224Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T09:34:23.224Z
Learning: Applies to nix-darwin/**/*.nix : Use Homebrew only for macOS-specific applications

Applied to files:

  • nix-darwin/config/homebrew.nix
📚 Learning: 2025-11-25T09:34:40.062Z
Learnt from: CR
Repo: shunkakinoki/dotfiles PR: 0
File: .cursor/rules/general.mdc:0-0
Timestamp: 2025-11-25T09:34:40.062Z
Learning: Document all major changes in Nix configurations

Applied to files:

  • nix-darwin/config/homebrew.nix
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: docker-build-push (linux/amd64, amd64, ubuntu-latest)
  • GitHub Check: docker-build-push (linux/arm64, arm64, ubuntu-24.04-arm)
  • GitHub Check: lua-neovim
  • GitHub Check: lua-hammerspoon
  • GitHub Check: e2e-run (NixOS, ubuntu-latest)
  • GitHub Check: e2e-run (MacOS, macos-latest)
  • GitHub Check: e2e-run (Ubuntu, ubuntu-latest)
  • GitHub Check: nix-nixos
  • GitHub Check: nix-linux
  • GitHub Check: nix-darwin
  • GitHub Check: Mesa Description
🔇 Additional comments (5)
home-manager/programs/neovim/lua/workspace.lua (1)

15-19: LGTM!

The WorkspaceRoot command implementation is correct, and the immediate setup() call is appropriate for a Neovim configuration module.

Also applies to: 21-23

home-manager/programs/neovim/init.lua (3)

4-5: LGTM!

Leader key configuration is standard and correct.


20-27: LGTM!

The dynamic init path resolution properly handles symlinks via fs_realpath and ensures the module search path includes the actual location of the init file.


32-44: LGTM on the modular architecture!

The refactoring from a monolithic configuration to discrete, purpose-driven modules (settings, plugins, autocmds, keymaps, lsp, etc.) significantly improves maintainability and organization. The loading order appears well-considered.

nix-darwin/config/homebrew.nix (1)

81-90: New Homebrew casks are valid macOS apps and keep style consistent

The additions of trae, visual-studio-code@insiders, and the switch to tailscale-app all point at valid Homebrew casks for macOS GUI/tools, so they fit the nix-darwin rule of using Homebrew only for macOS-specific applications and should behave as expected. (formulae.brew.sh) Formatting (2-space indentation, list layout, line length) also remains compatible with nixfmt/treefmt. Based on learnings, this looks good as-is; if you maintain multiple Macs, you might still want to run a quick brew info --cask for these tokens locally once to confirm availability in your tap set.

Comment on lines +1 to +3
---Set workspace-specific helpers and defaults.
---@return nil
local M = {}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Correct the return type annotation.

The docstring indicates @return nil, but the module actually returns a table M at line 23.

Apply this diff to fix the annotation:

 ---Set workspace-specific helpers and defaults.
----@return nil
+---@return table
 local M = {}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
---Set workspace-specific helpers and defaults.
---@return nil
local M = {}
---Set workspace-specific helpers and defaults.
---@return table
local M = {}
🤖 Prompt for AI Agents
In home-manager/programs/neovim/lua/workspace.lua around lines 1 to 3, the
docstring incorrectly states "@return nil" even though the module returns the
table M at the end; update the return annotation to reflect the actual return
value (e.g., "@return table" or "@return table M — module table") so the
documentation matches the code.

Comment on lines +7 to +13
vim.api.nvim_create_autocmd("FileType", {
pattern = "*",
callback = function()
vim.opt_local.shiftwidth = 2
vim.opt_local.tabstop = 2
end,
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Consider language-specific indentation preferences.

The FileType autocmd with pattern = "*" enforces 2-space indentation globally, overriding language-specific conventions. This may cause issues with:

  • Python (typically 4 spaces)
  • Go (tabs by convention)
  • Makefiles (tabs required)
  • Other languages with established style guides

Consider either excluding specific file types or documenting this as an intentional workspace-wide override.

If you want to keep the global 2-space default but respect certain file types, apply this diff:

   -- Ensure projects default to 2-space indents.
   vim.api.nvim_create_autocmd("FileType", {
-    pattern = "*",
+    pattern = { "*" },
     callback = function()
-      vim.opt_local.shiftwidth = 2
-      vim.opt_local.tabstop = 2
+      -- Skip file types that have strong conventions
+      local ft = vim.bo.filetype
+      if ft == "go" or ft == "make" or ft == "python" then
+        return
+      end
+      vim.opt_local.shiftwidth = 2
+      vim.opt_local.tabstop = 2
     end,
   })
🤖 Prompt for AI Agents
In home-manager/programs/neovim/lua/workspace.lua around lines 7 to 13, the
FileType autocmd with pattern="*" forcibly sets shiftwidth and tabstop to 2 for
all filetypes which overrides language-specific indentation (e.g., Python, Go,
Makefiles); change the autocmd to either (a) apply the 2-space defaults only to
a whitelist of filetypes that should use 2 spaces, or (b) keep the global
2-space default but add explicit guards that skip or set different values for
specific filetypes (at minimum: set python to shiftwidth=4, set go and make to
use tabs, and skip any other language with established conventions), and update
or add a comment documenting this behavior so future maintainers understand the
intentional exceptions.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

6 issues found across 22 files

Prompt for AI agents (all 6 issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="home-manager/programs/neovim/lua/treesitter.lua">

<violation number="1" location="home-manager/programs/neovim/lua/treesitter.lua:112">
`lookahead` must be configured inside the `select` module; placing it at the top level means the option is ignored and lookahead remains disabled.</violation>
</file>

<file name="home-manager/programs/neovim/lua/utils.lua">

<violation number="1" location="home-manager/programs/neovim/lua/utils.lua:93">
`M.copen()` never opens the quickfix window when the list has exactly one entry, preventing users from inspecting single quickfix results.</violation>
</file>

<file name="home-manager/programs/neovim/lua/autocmds.lua">

<violation number="1" location="home-manager/programs/neovim/lua/autocmds.lua:66">
Use the buffer-local filetype when detecting help buffers so the Help autocmd actually runs.</violation>
</file>

<file name="home-manager/programs/neovim/lua/lsp.lua">

<violation number="1" location="home-manager/programs/neovim/lua/lsp.lua:10">
Mapping code actions to plain &quot;ca&quot; in normal mode overrides the built-in change-around operator (e.g., `caw`, `ca(`), preventing users from performing those edits when an LSP is attached.</violation>
</file>

<file name="home-manager/programs/neovim/lua/plugins.lua">

<violation number="1" location="home-manager/programs/neovim/lua/plugins.lua:120">
`javascriptreact` and `typescriptreact` buffers never run eslint because those filetypes are missing from `lint.linters_by_ft`, so the save-time linting added below silently skips React files even though they use the same toolchain.</violation>

<violation number="2" location="home-manager/programs/neovim/lua/plugins.lua:126">
Create a dedicated augroup for this BufWritePost autocmd so that reloading the config doesn’t register duplicate lint callbacks.</violation>
</file>

Reply to cubic to teach it or ask questions. Re-run a review with @cubic-dev-ai review this PR

auto_install = true,
textobjects = {
enable = true,
lookahead = true,

@cubic-dev-ai cubic-dev-ai Bot Nov 28, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lookahead must be configured inside the select module; placing it at the top level means the option is ignored and lookahead remains disabled.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/programs/neovim/lua/treesitter.lua, line 112:

<comment>`lookahead` must be configured inside the `select` module; placing it at the top level means the option is ignored and lookahead remains disabled.</comment>

<file context>
@@ -0,0 +1,163 @@
+	auto_install = true,
+	textobjects = {
+		enable = true,
+		lookahead = true,
+		swap = {
+			enable = true,
</file context>
Fix with Cubic

end

function M.copen()
if vim.fn.getqflist({ size = 0 }).size > 1 then

@cubic-dev-ai cubic-dev-ai Bot Nov 28, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

M.copen() never opens the quickfix window when the list has exactly one entry, preventing users from inspecting single quickfix results.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/programs/neovim/lua/utils.lua, line 93:

<comment>`M.copen()` never opens the quickfix window when the list has exactly one entry, preventing users from inspecting single quickfix results.</comment>

<file context>
@@ -0,0 +1,104 @@
+end
+
+function M.copen()
+	if vim.fn.getqflist({ size = 0 }).size &gt; 1 then
+		vim.cmd(&quot;copen&quot;)
+	else
</file context>
Suggested change
if vim.fn.getqflist({ size = 0 }).size > 1 then
if vim.fn.getqflist({ size = 0 }).size > 0 then
Fix with Cubic

group = help_group,
pattern = { "*.txt" },
callback = function()
if vim.o.filetype == "help" then

@cubic-dev-ai cubic-dev-ai Bot Nov 28, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the buffer-local filetype when detecting help buffers so the Help autocmd actually runs.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/programs/neovim/lua/autocmds.lua, line 66:

<comment>Use the buffer-local filetype when detecting help buffers so the Help autocmd actually runs.</comment>

<file context>
@@ -0,0 +1,160 @@
+	group = help_group,
+	pattern = { &quot;*.txt&quot; },
+	callback = function()
+		if vim.o.filetype == &quot;help&quot; then
+			vim.cmd.wincmd(&quot;L&quot;)
+		end
</file context>
Suggested change
if vim.o.filetype == "help" then
if vim.bo.filetype == "help" then
Fix with Cubic

vim.keymap.set("n", "gi", vim.lsp.buf.implementation, opts)
vim.keymap.set("n", "gr", vim.lsp.buf.references, opts)
vim.keymap.set("n", "<leader>D", vim.lsp.buf.type_definition, opts)
vim.keymap.set("n", "ca", vim.lsp.buf.code_action, opts)

@cubic-dev-ai cubic-dev-ai Bot Nov 28, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mapping code actions to plain "ca" in normal mode overrides the built-in change-around operator (e.g., caw, ca(), preventing users from performing those edits when an LSP is attached.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/programs/neovim/lua/lsp.lua, line 10:

<comment>Mapping code actions to plain &quot;ca&quot; in normal mode overrides the built-in change-around operator (e.g., `caw`, `ca(`), preventing users from performing those edits when an LSP is attached.</comment>

<file context>
@@ -0,0 +1,71 @@
+	vim.keymap.set(&quot;n&quot;, &quot;gi&quot;, vim.lsp.buf.implementation, opts)
+	vim.keymap.set(&quot;n&quot;, &quot;gr&quot;, vim.lsp.buf.references, opts)
+	vim.keymap.set(&quot;n&quot;, &quot;&lt;leader&gt;D&quot;, vim.lsp.buf.type_definition, opts)
+	vim.keymap.set(&quot;n&quot;, &quot;ca&quot;, vim.lsp.buf.code_action, opts)
+	vim.keymap.set(&quot;n&quot;, &quot;&lt;leader&gt;rn&quot;, vim.lsp.buf.rename, opts)
+	vim.keymap.set(&quot;n&quot;, &quot;&lt;C-k&gt;&quot;, vim.lsp.buf.signature_help, opts)
</file context>
Suggested change
vim.keymap.set("n", "ca", vim.lsp.buf.code_action, opts)
vim.keymap.set("n", "<leader>ca", vim.lsp.buf.code_action, opts)
Fix with Cubic

typescript = { "eslint" },
}

vim.api.nvim_create_autocmd({ "BufWritePost" }, {

@cubic-dev-ai cubic-dev-ai Bot Nov 28, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create a dedicated augroup for this BufWritePost autocmd so that reloading the config doesn’t register duplicate lint callbacks.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/programs/neovim/lua/plugins.lua, line 126:

<comment>Create a dedicated augroup for this BufWritePost autocmd so that reloading the config doesn’t register duplicate lint callbacks.</comment>

<file context>
@@ -0,0 +1,130 @@
+	typescript = { &quot;eslint&quot; },
+}
+
+vim.api.nvim_create_autocmd({ &quot;BufWritePost&quot; }, {
+	callback = function()
+		lint.try_lint()
</file context>
Fix with Cubic

require("colorizer").setup()

local lint = require("lint")
lint.linters_by_ft = {

@cubic-dev-ai cubic-dev-ai Bot Nov 28, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

javascriptreact and typescriptreact buffers never run eslint because those filetypes are missing from lint.linters_by_ft, so the save-time linting added below silently skips React files even though they use the same toolchain.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/programs/neovim/lua/plugins.lua, line 120:

<comment>`javascriptreact` and `typescriptreact` buffers never run eslint because those filetypes are missing from `lint.linters_by_ft`, so the save-time linting added below silently skips React files even though they use the same toolchain.</comment>

<file context>
@@ -0,0 +1,130 @@
+require(&quot;colorizer&quot;).setup()
+
+local lint = require(&quot;lint&quot;)
+lint.linters_by_ft = {
+	python = { &quot;pylint&quot; },
+	javascript = { &quot;eslint&quot; },
</file context>
Fix with Cubic

@shunkakinoki
shunkakinoki merged commit 39ad4d5 into main Nov 28, 2025
23 checks passed
@shunkakinoki
shunkakinoki deleted the nvim-revamp branch November 28, 2025 05:58
@coderabbitai coderabbitai Bot mentioned this pull request Dec 10, 2025
@coderabbitai coderabbitai Bot mentioned this pull request May 14, 2026
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants