Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

201 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Neovim Configuration

中文文档

A modern Neovim configuration built with Lua and lazy.nvim. Aligned with LazyVim conventions for keybindings and plugin choices, with support for Go, C/C++, Python, Java, Web, Bash, JSON, YAML, and LaTeX development.

Requirements

Required:

  • Neovim >= 0.11.0 (uses vim.lsp.config/vim.lsp.enable, vim.hl, vim.diagnostic.jump)
  • Git
  • A Nerd Font for icon display
  • ripgrep (rg) — powers Snacks.picker.grep / live_grep / :grep
  • fd — file finder (used by venv-selector and some pickers)

Optional (feature-specific):

  • lazygit<leader>gg (project) / <leader>gf (file history)
  • tmux — wraps Claude Code TUI inside :terminal to prevent flicker; auto-detected (see Terminal Integration)
  • GitHub CLI — authenticated gh for <leader>gh GitHub pickers and status
  • Claude Code or Codex — selected native coding agent
  • Node.js >= 22 + npm — CodeCompanion ACP bridge processes
  • ANTHROPIC_API_KEY or OPENAI_API_KEY — optional; selected provider's CodeCompanion HTTP inline/command prompts
  • cowsay + lolcat — dashboard banner (silently skipped if either is missing)

Quick install (macOS):

brew install neovim git gh ripgrep fd lazygit tmux cowsay lolcat node
brew install --cask font-jetbrains-mono-nerd-font  # or any Nerd Font
gh auth login                                      # once, for GitHub pickers
npm install -g @agentclientprotocol/claude-agent-acp @agentclientprotocol/codex-acp

Language toolchainsonly if you want the matching Mason packages to install:

  • Go — required for gopls, gofumpt, gomodifytags, impl, delve
  • Python >= 3.10 — required for black (a pyenv or uv-managed interpreter works)
  • Node.js + npm — required for eslint-lsp, css-lsp, html-lsp, json-lsp, yaml-language-server, tailwindcss-language-server, vtsls, bash-language-server
  • JDK 17+ — required for jdtls (Java). This config expects SDKMAN! at ~/.sdkman/candidates/java/current (see lua/lang/java.lua)
  • TeX Live + Skim (LaTeX) — brew install --cask mactex-no-gui for latexmk/latexindent/chktex, and brew install --cask skim for the SyncTeX PDF viewer. texlab is installed by Mason. For inverse search set Skim → Preferences → Sync → Custom: command nvim, arguments --headless -c "VimtexInverseSearch %line '%file'"

If a Mason package fails to install, run :Mason (UI) or :MasonLog (raw log) to see the underlying error. The most common cause is a missing toolchain from the list above.

Installation

# Backup existing config
mv ~/.config/nvim ~/.config/nvim.backup

# Clone
git clone https://github.com/huiyu/nvim.git ~/.config/nvim

# Launch Neovim — lazy.nvim auto-installs all plugins
nvim

Project Structure

~/.config/nvim/
├── AGENTS.md                # Repository guidance for coding agents
├── CLAUDE.md                # Claude Code import of AGENTS.md
├── init.lua                  # Entry point
├── lua/
│   ├── options.lua           # Vim options
│   ├── mappings.lua          # Imperative core keymaps (side effects)
│   ├── whichkey_spec.lua     # which-key groups + spec-registered keymaps (data)
│   ├── autocmds.lua          # Autocommands
│   ├── bootstrap.lua         # lazy.nvim setup
│   ├── ai/                    # Provider config + native Claude/Codex facade
│   ├── config/
│   │   └── health.lua        # `:checkhealth config` provider
│   ├── lang/                 # Language-specific configs
│   │   ├── bash.lua
│   │   ├── c.lua             # C / C++
│   │   ├── frontend.lua      # HTML / CSS / Tailwind
│   │   ├── go.lua
│   │   ├── java.lua
│   │   ├── json.lua
│   │   ├── python.lua
│   │   ├── tex.lua           # LaTeX (VimTeX + texlab)
│   │   ├── typescript.lua    # JS / TS language (LSP, format, DAP)
│   │   └── yaml.lua
│   ├── plugin/
│   │   ├── editor/           # Editor enhancement plugins
│   │   ├── lsp/              # LSP, completion, formatting, debugging
│   │   ├── ui/               # UI and theme plugins
│   │   └── vcs/              # Git integration
│   └── util/                 # Utility modules
└── docs/                     # DIAGNOSTICS.md, UTILITIES.md

Plugins

UI

Plugin Description
solarized-osaka Colorscheme
lualine Status line
bufferline Buffer tabs with pin/close/pick
noice Enhanced cmdline, messages, notifications
treesitter Syntax highlighting, text objects
treesitter-context Sticky function/class header (<leader>uC)
nvim-ts-autotag Auto-close HTML/JSX tags
nvim-ufo Modern code folding
todo-comments TODO/FIXME highlights
illuminate Highlight word under cursor
colorizer Color code highlighting
render-markdown In-editor markdown rendering

Editor

Plugin Description
flash Fast navigation with labels
which-key Keybinding help popup
snacks Picker (fuzzy finder), dashboard, file explorer, terminal, indent guides, smooth scroll, notifications, rename
aerial Code outline / symbol navigation
grug-far Search and replace
harpoon Quick file navigation (<leader>1-9)
yanky Yank history ring
dial Enhanced increment/decrement (booleans, dates, etc.)
refactoring Extract function/variable, inline
mini.ai Enhanced text objects
mini.splitjoin Toggle single-line/multi-line (gS)
nvim-surround Surround manipulation
nvim-autopairs Auto-close pairs
persistence Session management
guess-indent Auto-detect indentation

LSP & Development

Plugin Description
nvim-lspconfig LSP configuration
mason LSP/DAP/linter/formatter installer
blink.cmp Completion engine with friendly-snippets
conform Code formatting (with autoformat toggle)
nvim-lint Linting
nvim-dap Debug Adapter Protocol
neotest Testing framework
neogen Generate annotations/docstrings
SchemaStore JSON/YAML schema validation
lazydev Lua development (type completion)
claudecode Native Claude Code integration (Claude provider only)
CodeCompanion Provider-aware ACP chat plus HTTP inline/command prompts
codecompanion-history Auto-saved, project-aware CodeCompanion chat history

Version Control

Plugin Description
gitsigns Git signs, hunk actions, blame
diffview Diff and file history viewer

Language Support

Language LSP Formatter Linter Test Debug
C / C++ clangd clang-format - - codelldb
Go gopls gopls organize imports + gofumpt golangci-lint neotest-golang nvim-dap-go
Python basedpyright, ruff black ruff neotest-python nvim-dap-python
Java jdtls (+ Lombok) jdtls - java-test java-debug-adapter
TypeScript/JS vtsls prettier eslint - js-debug-adapter
HTML/CSS html, cssls, tailwindcss prettier - - -
JSON jsonls + SchemaStore prettier - - -
YAML yamlls + SchemaStore prettier - - -
Bash bashls shfmt - - -
LaTeX texlab (+ VimTeX) latexindent chktex - -
Lua lua_ls - - - -

LaTeX Workflow

LaTeX is split between two tools: VimTeX drives compilation/viewing/motions, while texlab provides LSP intelligence (completion, goto, label rename) and chktex linting. They are configured not to overlap — texlab's own build is disabled so only VimTeX compiles.

One-time setup

brew install --cask mactex-no-gui   # TeX Live: latexmk, latexindent, chktex
brew install --cask skim            # PDF viewer with SyncTeX

texlab installs itself through Mason on first launch — no extra step. For inverse search (click in the PDF → jump to source), set Skim → Preferences → Sync → Preset: Custom, Command nvim, Arguments:

--headless -c "VimtexInverseSearch %line '%file'"

Daily use — open any .tex file, then:

  • <localleader>ll (\ll) — start continuous compilation (recompiles on save)
  • <localleader>lv (\lv) — forward search: open/jump Skim to the cursor's line
  • <localleader>lt (\lt) — table of contents; \lk clean, \le errors
  • Save the file to auto-format with latexindent (toggle with <leader>uf)

The same actions are mirrored under the <leader>c (Code) group for which-key discoverability:

Key Action
<leader>cb Compile (toggle continuous)
<leader>cv View PDF in Skim
<leader>cs Stop compilation
<leader>ck Clean aux files
<leader>ct Toggle table of contents
<leader>ce Show error list
<leader>cx One-shot latexmk build to PDF

TeX buffers also enable soft wrap and spell by default (toggle with <leader>uw / <leader>us).

Keybinding Reference

Leader: Space | Local leader: \ | Keybinding guide: <leader>?

Which Prefix? (Intent → Key)

One design rule governs everything: the more frequent the action, the faster the prefix. Modifier chords (Ctrl/Shift/Alt) are instant muscle memory; sequence prefixes (g, [/], z) move the cursor; <leader> is the command palette — slowest, but which-key has your back.

Start from what you want to do:

I want to… Use Examples
Run a command / manage things <leader> + domain letter <leader>gs git status, <leader>bd delete buffer, <leader>ca code action
Step to the next/prev one of something ] / [ + kind ]d diagnostic, ]h hunk, ]b buffer — repeat to iterate
Jump to something about the symbol under cursor g gd definition, gr references, gI implementation — one shot
Do an instant, every-minute action Ctrl <C-h/j/k/l> windows, <C-s> save, <C-/> terminal
Cycle through the bufferline Shift <S-h> / <S-l>
Move something (not the cursor) Alt <A-j> / <A-k> move line
Fly to any spot I can see s Flash jump: s + 2 chars + label

Mnemonic: Space commands, brackets step, g resolves, Ctrl acts, Shift cycles, Alt moves, s flies.

Two distinctions worth training deliberately:

  • ]d vs gd — brackets answer "where is the next one from here?" (position-based, repeatable); g answers "where is THE definition of this?" (semantic, lands in one jump).
  • <S-h> is literally H — it shadows native H/L (jump to top/bottom of visible screen). Deliberate trade: buffer switching is far more frequent, and gg/G/relative jumps cover the loss (M is untouched).

Trigger Key Prefixes

Press any prefix and wait for which-key popup to see available keys.

Prefix Category
<leader> Main command palette (all groups below)
g Goto / LSP (gd definition, gr references, K hover, gI impl, gy type def, gD declaration, gK signature, gS splitjoin)
s / S Flash jump / Treesitter jump
[ / ] Prev / Next navigation (b buffer, d diagnostic, e error, w warning, h hunk, q quickfix, t todo, y yank, B move buffer)
z Folds / Spelling (zR open all, zM close all, zK peek)
<C-w> Window operations

Top-level Shortcuts

Key Action
<C-s> Save file (all modes)
<Esc> Clear search highlight
<C-/> Toggle terminal
<C-h/j/k/l> Window navigation
<C-Up/Down/Left/Right> Window resize
<A-j> / <A-k> Move line up/down (n, i, v)
<S-h> / <S-l> Prev / Next buffer
<leader><space> Smart find (buffers + recent + files, all filtered to cwd, frecency-boosted)
<leader>. Find file in cwd (incl. hidden + gitignored; heavy build/dep dirs excluded)
<leader>/ Search project grep (incl. hidden + gitignored; heavy build/dep dirs excluded)
<leader>, Buffers
<leader>: Command history
<leader>' Resume last picker
``` Last buffer (alternate)
<leader>? Keybinding guide
<leader>l Lazy (plugin manager)
<leader>n Notification history
<leader>e / <leader>E File tree / File explorer
<leader>- / <leader>| Split below / right
<leader>1-9 Harpoon: jump to file 1-9
<leader>h / <leader>H Harpoon quick menu / add file
<leader>p Yank history — see Yanky

Leader Groups

Group Key Description
Find/Files <leader>f ff files in cwd, fF from buffer dir, fd browse directory, fe explorer (with ignored), fr recent, fb buffers, fg git files, fp projects, fc nvim config, fn new, fs/fS save/save-as, fR rename, fD delete, fy/fY yank path (abs/project), ft/fT terminal
Search <leader>s sb buffer, sB open buffers, sd current dir, sp project, sw word, ss/sS symbols (buffer/workspace), sR resume, sh help, sk keymaps, sm marks, sj jumps, sc/sC cmd history/cmds, s" registers, sM man, sr/sW replace, st/sT todos, sn{a,d,h,l,t} noice (all/dismiss/history/last/pick)
Code <leader>c ca action, cr rename, cf format, cd diagnostics, cm Mason, cl LSP info, cn generate annotations, co organize imports, cO outline, cs/cS symbols (buffer/workspace), cv select venv (py), cp markdown preview (md), cP browse cwd markdown → preview, cx run current file (by filetype: go/c/cpp/py/js/ts/sh), cR rebuild gopls index (go)
Buffer <leader>b bd delete, bo delete others, bD delete+window, bl/br delete left/right, bj pick, bp pin, bP close unpinned
Debug <leader>d db/dB breakpoint/conditional, dc/da continue/with-args, dC run to cursor, dg goto line, di step into, do step out, dO step over, dj/dk down/up frame, dP pause, dr REPL, ds session, dw widgets, dt terminate, dl run last
Git <leader>g gs status, gb branches, gc/gC commits, gl/gL blame, gp preview, gr/gR reset, gS stage/unstage, gT toggle line blame, gd diff, gv diffview, gm diff main, gM diff pick ref, gV file history, gH git log, gh* GitHub
Test <leader>t tm test method, td debug method, tf test file, tS summary, to output, tD/th show/hide diagnostic
Terminal <leader>T T1-9 open/toggle dedicated terminals, Td fix agent TUI drift, Tx close terminal buffer
Toggle/UI <leader>u uf/uF autoformat, us spell, uw wrap, ul/uL numbers, ud diagnostics, uh inlay hints, uT treesitter, uc conceal, ub background, un dismiss notifs, uR markdown render
Diagnostics <leader>x xx/xX diagnostics (project/buffer), xL/xQ loclist/quickfix picker, xl/xq toggle loclist/quickfix window, xt/xT todos
Refactor <leader>r rf extract function, rF extract function to file, rx extract variable, ri inline, rb extract block, rB extract block to file, rs select
AI <leader>a Native: ac toggle, af focus, ar resume picker, aR continue last, am model, ab add buffer, as attach selection (v). Claude-only: aS, aa/ad. CodeCompanion: ap{c,t,a,i,b,h} chat/toggle/actions/inline/add selection/history
Window <leader>w ww other window, wd delete, wo close others, w= equalize, wm zoom
Quit/Session <leader>q qq/qQ quit, qs save session, ql load last, q. load current
Tab <leader><tab> <tab><tab> new, d close, ]/[ next/prev, ` last used (alternate), l/f rightmost/first, o close others, s list all

GitHub (<leader>gh)

Key Action
f / F Open the current file/visual lines on its branch / as a commit permalink
r Open the repository home page
i / I Open issues / all issues in the Snacks GitHub picker
p / P Open pull requests / all pull requests in the Snacks GitHub picker
c Show the current branch PR and its available actions
a Open the repository's GitHub Actions page
n Open GitHub notifications
s Show account-wide gh status in a floating window

Issue and PR mutations are intentionally not assigned global mappings. In a Snacks GitHub picker, press <cr> to choose an action such as opening details, commenting, reviewing, or merging. These mappings require an authenticated GitHub CLI (gh auth status); :checkhealth config reports whether it is found.

Diffview (in-view keys)

Launch keys live in the Git group (<leader>gv/gm/gM/gV/gH). Once inside a diff view these buffer-local keys apply — press g? for the full context-sensitive help:

Key Action
<tab> / <s-tab> Next / previous file's diff
[F / ]F First / last file
<leader>e / <leader>b Focus / toggle the file panel
gf Open the file in the previous tabpage
<C-w><C-f> / <C-w>gf Open the file in a split / new tab
g<C-x> Cycle diff layout
- / s, S / U (file panel) stage/unstage entry, stage/unstage all
X (file panel) restore entry to the left side
i / f (file panel) toggle list/tree, flatten empty dirs
L (file panel) open commit log
[x / ]x Previous / next merge conflict
<leader>c{o,t,b,a} Resolve conflict: ours / theirs / base / all (uppercase = whole file)
dx Delete the conflict region
y (file history) copy the commit hash

Disabled inside Diffview: the file/buffer openers <leader>f, <leader><space>, <leader>., <leader>/, <leader>, are neutralized in diff buffers — they would load a file into a diff window and break the layout, so they show a hint instead (exit with <leader>gq first). <leader>b/e/c* intentionally keep diffview's own actions rather than the global Buffer/Explorer/Code groups. Configured in lua/plugin/vcs/diffview.lua.

Yanky (Enhanced Yank/Paste)

Key Action
y / p / P Yank / Put (with history)
[y / ]y Cycle through yank history
<leader>p Open yank history (:YankyRingHistory via snacks ui-select)
<leader>y (v) Yank selection to unnamed register
<leader>Y (v) Yank selection to system clipboard (+)

Terminal Integration

Native coding-agent terminals automatically repair stale libvterm cells when entering Terminal-mode, both on initial open and when returning from terminal Normal mode. If a TUI still drifts, exit terminal input with <Esc><Esc> and use <leader>Td as a manual fallback. Opening a numbered bottom terminal also repairs the visible agent after the layout changes.

AI provider selection

One Nvim process selects one provider at startup. Claude remains the default; the native and CodeCompanion shortcuts stay unchanged. The shell aliases used by this setup are:

vi                 # default provider (Claude unless overridden)
vic                # NVIM_AI_PROVIDER=claude nvim
vix                # NVIM_AI_PROVIDER=codex CODEX_HOME="$HOME/.codex-oauth" nvim

<leader>as attaches the visual selection to the native agent's composer and does not submit it, leaving room for an instruction. With Codex, a saved buffer becomes an @path lines X-Y draft. For a modified or unnamed buffer, the exact selected text is pasted instead because Codex file mentions read the saved file. Add the instruction you want, then press Enter yourself.

The same setting selects CodeCompanion's ACP Chat agent (claude_code / codex). Chat therefore uses the coding agent's stateful protocol and tools; Inline and command prompts remain lightweight HTTP interactions (anthropic / openai_responses) and require the matching API key. Codex ACP uses ChatGPT authentication and inherits CODEX_HOME from vix.

CodeCompanion chats are auto-saved by codecompanion-history. Open them with <leader>aph (or :CodeCompanionHistory); inside a chat, gh opens the same history browser. Entries use the Snacks picker and can be renamed manually; automatic model-generated titles are disabled to avoid an extra request. History restores the local CodeCompanion transcript. To continue the agent's actual stateful ACP session, use /resume from a fresh ACP chat.

Run :AIInfo to inspect the resolved Native/ACP/HTTP mapping and :checkhealth config to see missing CLIs, ACP bridges, or HTTP credentials.

Shift+Enter (iTerm2)

When running terminal apps inside Neovim (e.g. Claude Code), Shift+Enter requires iTerm2 configuration:

iTerm2 setup: Settings → Profiles → Keys → Key Mappings → Add:

  • Shortcut: Shift + Return
  • Action: Send Escape Sequence
  • Value: [13;2u

Claude Code tmux wrapper

Claude Code is launched inside a dedicated tmux server when run via claudecode.nvim — see lua/plugin/lsp/ai.lua.

Why: Claude's Ink-based TUI emits DEC mode 2026 (Synchronized Output) escape sequences for atomic frame updates. Nvim's :terminal buffer does not understand this protocol, so without the wrapper you get mid-frame tearing — status bar double-renders, lines bleeding into adjacent rows. tmux absorbs the 2026 sequences, composes whole frames, and emits plain ANSI that nvim's :terminal can render cleanly. (This is independent of the host terminal: Ghostty / WezTerm / iTerm2 all hit the same issue because the broken layer is nvim's :terminal, not them.)

Trade-off: Inside the wrapped tmux, CJK wide-character widths can disagree between tmux, the host terminal, and Claude's string-width library. This produces minor misalignment in box-bordered UI (TODO list, diff preview, session recap). Much less disruptive than the tearing without the wrapper.

Overrides:

  • CLAUDE_WRAP_TMUX=0 nvim — disable for one-off A/B testing
  • vim.g.claude_wrap_tmux = false in init.lua — disable permanently
  • Default: on

Tip — suppress the recap CJK box: Claude Code's session recap is the most visible CJK width offender. Set "awaySummaryEnabled": false in ~/.claude/settings.json to suppress it. This is Claude Code's global config, not nvim's.

Environment Variables

Variable Description
NVIM_AI_PROVIDER claude (default) or codex; selects the native agent, CodeCompanion ACP Chat, and HTTP inline adapter for this Nvim process
NVIM_LOG_LEVEL util.logger threshold: DEBUG/INFO/WARN/ERROR (default WARN)
NVIM_DEV=1 Sets util.logger to DEBUG (verbose logging)
CLAUDE_WRAP_TMUX 1/0 — override default Claude Code tmux wrap. Default on. See Claude Code tmux wrapper.
CLAUDE_CHROME 1/0 — enable or disable Claude in Chrome for the native Claude process. Default on.

Diagnostics

For troubleshooting (slow startup, LSP not attaching, missing formatter, etc.) see docs/DIAGNOSTICS.md. Run :checkhealth config to verify external dependencies, key Mason packages, and the Neovim version.

Customization

Add a plugin — create a file in the appropriate lua/plugin/*/ directory.

Add language support, an LSP server, or a formatter — create or edit the matching contribution in lua/lang/. Language files extend the shared nvim-lspconfig, Conform, lint, Treesitter, DAP, and test specs; the files in lua/plugin/lsp/ contain editor-wide defaults only.

Tune file/grep search scope — the file (<leader>.) and grep (<leader>/) pickers show hidden and gitignored files (hidden/ignored in lua/plugin/editor/snacks.lua). .git/ is always excluded; heavy build/dependency dirs (node_modules, target, .venv, Pods, …) are skipped via the shared search_exclude list in the same file. Add a dir to that list to hide it, or remove one to search it. Note: exclude drops any dir of that name unconditionally — even git-tracked source — so generic names (bin, out, vendor) are intentionally left out.

License

This configuration is provided as-is for personal use.

About

My Personal Neovim Config

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages