Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Repository context

This is a personal fork of `nvim-lua/kickstart.nvim`. Two remotes exist:
- `origin` → `bhendo/kickstart.nvim` (the fork)
- `upstream` → `nvim-lua/kickstart.nvim` (kickstart's canonical repo)

**PRs ALWAYS target origin (the fork), NEVER upstream.** When using `gh pr create`, pass `--repo bhendo/kickstart.nvim` explicitly so it can't auto-select upstream.

The fork uses `vim.pack` (Neovim's built-in plugin manager), not `lazy.nvim`. Both this fork and upstream independently migrated; the migrations converged.

## Architecture

The config is split into two layers:

**`init.lua`** — kept as close to upstream as possible to minimize merge conflicts. Currently differs from `upstream/master` by 4 lines only:
- `vim.g.have_nerd_font = true`
- `vim.o.relativenumber = true`
- blink.cmp `preset = 'super-tab'`
- `require 'custom.plugins'` uncommented (the upstream-provided extension hook)

When editing `init.lua`, prefer extracting the change to a custom plugin over modifying `init.lua` directly. The first three lines above only stay in `init.lua` because `have_nerd_font` is read inline by mini.icons during init, `relativenumber`/blink preset would be slightly awkward to override post-init, and the loader line is the intended hook. New customizations should go to `lua/custom/plugins/`.

**`lua/custom/plugins/`** — all personal customizations. The loader at `lua/custom/plugins/init.lua` requires each file in a deliberate order (kickstart enables → LSP/mason extras → formatting/completion overrides → editor → language-specific → keymaps). Order matters: later files can depend on plugins set up earlier.

Each custom plugin file is self-contained and follows the same pattern as `lua/kickstart/plugins/*.lua`:
1. `vim.pack.add { ... }` to declare plugin source
2. `require('plugin').setup { ... }` (or equivalent) to configure
3. Any related keymaps/autocmds inline

`conform.setup` and other plugins that use `tbl_deep_extend` can be re-called in custom files to merge with `init.lua`'s base config (see `lua/custom/plugins/conform.lua`).

`lua/kickstart/plugins/*.lua` are kickstart's *optional* plugin enables. Adding one to the loader in `lua/custom/plugins/init.lua` opts into it without modifying `init.lua`.

## Common commands

Smoke-test the config (used to verify after merges/refactors):
```sh
nvim --headless "+lua print('config loaded ok')" "+qa"
```

Format Lua files (stylua config in `.stylua.toml`, uses 160-col width):
```sh
stylua init.lua lua/
```

Plugin management (run inside nvim):
- `:lua vim.pack.update(nil, { offline = true })` — inspect plugin state
- `:lua vim.pack.update()` — fetch updates (`:write` applies, `:quit` cancels)
- `:checkhealth` — diagnose config issues

## Working with upstream

To pull in upstream changes, create a `merge/upstream-YYYY-MM` branch off `master`, run `git merge upstream/master`, and resolve conflicts. The conflicts are typically:
- `init.lua` — keep `HEAD` on the 4 personal lines, accept upstream elsewhere
- `lua/custom/plugins/init.lua` — keep `HEAD` (our ordered loader)
- `.gitignore` — keep `HEAD` (has `.worktrees/`)
- `README.md` — usually auto-merges

After resolving, run the headless smoke-test before committing.

## Conventions

- Stylua: 160-col, single quotes, no parens on single-arg calls, collapse simple statements.
- Comments in custom plugin files explain *why* something is done a certain way (e.g., load-order dependencies, why a setup is re-called); they are not docstrings of *what* the code does.
- New custom plugins are added by creating `lua/custom/plugins/<name>.lua` and adding a `require 'custom.plugins.<name>'` line in the appropriate section of `lua/custom/plugins/init.lua`.
44 changes: 33 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ fork to your machine using one of the commands below, depending on your OS.
> Your fork's URL will be something like this:
> `https://github.com/<your_github_username>/kickstart.nvim.git`

You likely want to remove `lazy-lock.json` from your fork's `.gitignore` file
too - it's ignored in the kickstart repo to make maintenance easier, but it's
[recommended to track it in version control](https://lazy.folke.io/usage/lockfile).
You likely want to remove `nvim-pack-lock.json` from your fork's `.gitignore`
file too - it's ignored in the kickstart repo to make maintenance easier, but
it's recommended to track it in version control (see `:help vim.pack-lockfile`).

#### Clone kickstart.nvim

Expand Down Expand Up @@ -111,8 +111,10 @@ Start Neovim
nvim
```

That's it! Lazy will install all the plugins you have. Use `:Lazy` to view
the current plugin status. Hit `q` to close the window.
That's it! `vim.pack` will install all the plugins from your config. Use
`:lua vim.pack.update(nil, { offline = true })` to inspect plugin state and
`:lua vim.pack.update()` to fetch updates (`:write` applies updates, `:quit`
cancels them).

#### Read The Friendly Documentation

Expand Down Expand Up @@ -146,7 +148,8 @@ examples of adding popularly requested plugins.
`~/.local/share/nvim-kickstart`. You can apply this approach to any Neovim
distribution that you would like to try out.
* What if I want to "uninstall" this configuration:
* See [lazy.nvim uninstall](https://lazy.folke.io/usage#-uninstalling) information
* Remove your config directory and local data directory (for example,
`~/.config/nvim` and `~/.local/share/nvim`).
* Why is the kickstart `init.lua` a single file? Wouldn't it make sense to split it into multiple files?
* The main purpose of kickstart is to serve as a teaching tool and a reference
configuration that someone can easily use to `git clone` as a basis for their own.
Expand All @@ -167,17 +170,36 @@ After installing all the dependencies continue with the [Install Kickstart](#ins
#### Windows Installation

<details><summary>Windows with Microsoft C++ Build Tools and CMake</summary>
Installation may require installing build tools and updating the run command for `telescope-fzf-native`
Kickstart's default config is make-only for `telescope-fzf-native.nvim`.
If `make` is unavailable, the plugin is skipped.

See `telescope-fzf-native` documentation for [more details](https://github.com/nvim-telescope/telescope-fzf-native.nvim#installation)
Recommended: install `make` (see the chocolatey section below).

This requires:
If you want a CMake-only setup, customize `init.lua` in two places:

- Install CMake and the Microsoft C++ Build Tools on Windows
1. Include `telescope-fzf-native.nvim` when `cmake` is available:

```lua
{'nvim-telescope/telescope-fzf-native.nvim', build = 'cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release && cmake --build build --config Release && cmake --install build --prefix build' }
if vim.fn.executable 'make' == 1 or vim.fn.executable 'cmake' == 1 then
table.insert(plugins, gh 'nvim-telescope/telescope-fzf-native.nvim')
end
```

2. In the `PackChanged` hook, use CMake when `make` is unavailable:

```lua
if name == 'telescope-fzf-native.nvim' then
if vim.fn.executable 'make' == 1 then
run_build(name, { 'make' }, ev.data.path)
elseif vim.fn.executable 'cmake' == 1 then
run_build(name, { 'cmake', '-S.', '-Bbuild', '-DCMAKE_BUILD_TYPE=Release' }, ev.data.path)
run_build(name, { 'cmake', '--build', 'build', '--config', 'Release', '--target', 'install' }, ev.data.path)
end
return
end
```

See `telescope-fzf-native` documentation for [build details](https://github.com/nvim-telescope/telescope-fzf-native.nvim#installation).
</details>
<details><summary>Windows with gcc/make using chocolatey</summary>
Alternatively, one can install gcc and make which don't require changing the config,
Expand Down
2 changes: 1 addition & 1 deletion init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -877,7 +877,7 @@ do
-- the rust implementation via `'prefer_rust_with_warning'`
--
-- See `:help blink-cmp-config-fuzzy` for more information
fuzzy = { implementation = 'lua' },
fuzzy = { implementation = 'prefer_rust' },

-- Shows a signature help window while you type arguments for a function
signature = { enabled = true },
Expand Down
12 changes: 12 additions & 0 deletions lua/custom/plugins/filetypes.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
-- Filetype registrations Neovim doesn't ship by default.
--
-- gotmpl: Go templates (Helm charts, k8s manifests, Hugo). gopls advertises
-- support but Neovim has no built-in detection rule, so :checkhealth gopls
-- warns about the unknown filetype.

vim.filetype.add {
extension = {
gotmpl = 'gotmpl',
tpl = 'gotmpl',
},
}
4 changes: 4 additions & 0 deletions lua/custom/plugins/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
-- Order matters here: kickstart enables come first (they install dap, mason
-- extras, etc.) so later customizations can build on them.

-- Environment / filetype tweaks (no plugin deps; safe to load first)
require 'custom.plugins.providers'
require 'custom.plugins.filetypes'

-- Kickstart optional plugins (vim.pack-based)
require 'kickstart.plugins.debug'
require 'kickstart.plugins.indent_line'
Expand Down
6 changes: 5 additions & 1 deletion lua/custom/plugins/markdown.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@
-- Depends on nvim-treesitter and mini.nvim, both of which init.lua already adds.

vim.pack.add { 'https://github.com/MeanderingProgrammer/render-markdown.nvim' }
require('render-markdown').setup {}
require('render-markdown').setup {
-- We don't write LaTeX math in markdown; disabling avoids needing the
-- latex treesitter parser plus utftex/latex2text on the system.
latex = { enabled = false },
}
9 changes: 9 additions & 0 deletions lua/custom/plugins/providers.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-- Disable Neovim's remote plugin host providers we don't use.
-- Providers host plugins WRITTEN in these languages (e.g. legacy Deoplete in Python);
-- they are unrelated to LSP support for editing files in those languages.
-- All our plugins are Lua, so none of these hosts are needed.

vim.g.loaded_node_provider = 0
vim.g.loaded_perl_provider = 0
vim.g.loaded_python3_provider = 0
vim.g.loaded_ruby_provider = 0