Auto-detect and display all your Neovim keymaps in a beautiful, searchable cheatsheet
Features • Quick Start • Installation • Configuration • Commands • API
Ever wondered "what was that keymap again?" or wanted to see all your keymaps in one place? keymaps.nvim automatically discovers every keymap in your Neovim config and presents them in a searchable, categorized cheatsheet.
- No manual registration required
- Works with any plugin's keymaps
- Knows which plugin defined each keymap
- Export to Markdown, HTML, or JSON for documentation
| Feature | Description |
|---|---|
| Auto-detection | Scans all keymaps via nvim_get_keymap() across all modes (n, i, v, x, s, o, c, t) |
| Vim Motions Built-in | Includes 220+ Vim motions with descriptions (h/j/k/l, w/e/b, text objects, operators, and more) |
| Smart Categorization | Automatically groups keymaps into categories: LSP, Git, Navigation, Harpoon, Telescope, and more |
| Source Detection | Uses debug.getinfo() to identify which plugin defined each keymap |
| Telescope Integration | Beautiful fuzzy finder with preview (graceful fallback to floating window) |
| Export | Generate Markdown, interactive HTML, or JSON documentation |
| Usage Tracking | Track which keymaps you actually use and see statistics |
| Auto-refresh | Automatically updates when your config files change |
| Zero Config | Works out of the box with sensible defaults |
keymaps.nvim includes 220+ Vim motions with clear descriptions, so you get a complete reference alongside your custom keymaps:
| Category | Examples |
|---|---|
| Character/Word | h j k l w e b W E B ge |
| Line | 0 ^ $ g_ + - | |
| Vertical | gg G { } ( ) [[ ]] % |
| Screen | H M L <C-f> <C-b> <C-d> <C-u> zz zt zb |
| Search/Find | / ? n N * # f F t T ; , |
| Jumps | <C-o> <C-i> gd gD gf <C-]> g; g, |
| Text Objects | iw aw ip ap i) a) i" a" it at |
| Operators | d c y > < = gq gu gU |
| Commands | dd yy cc p P u <C-r> . J |
| Diff/Spell | [c ]c [s ]s z= zg |
| Folds | zo zc za zR zM zj zk |
| Windows | <C-w>s <C-w>v <C-w>h/j/k/l <C-w>= |
Smart deduplication: If you've remapped a motion (e.g.,
gdfor LSP), your version takes precedence.
Disable with include_motions = false if you prefer a leaner view.
-- lazy.nvim (recommended)
{
"abdul-hamid-achik/keymaps.nvim",
opts = {},
keys = {
{ "<leader>?", "<cmd>Keymaps<cr>", desc = "Show Keymaps" },
},
}Then press <leader>? to open the cheatsheet!
{
"abdul-hamid-achik/keymaps.nvim",
dependencies = {
"nvim-telescope/telescope.nvim", -- optional, for fuzzy finding
},
opts = {
-- your configuration (see below)
},
keys = {
{ "<leader>?", "<cmd>Keymaps<cr>", desc = "Show Keymaps" },
},
}use {
"abdul-hamid-achik/keymaps.nvim",
requires = {
"nvim-telescope/telescope.nvim", -- optional
},
config = function()
require("keymaps").setup({
-- your configuration
})
end,
}Plug 'nvim-telescope/telescope.nvim' " optional
Plug 'abdul-hamid-achik/keymaps.nvim'
lua require("keymaps").setup()git clone https://github.com/abdul-hamid-achik/keymaps.nvim \
~/.local/share/nvim/site/pack/plugins/start/keymaps.nvimClick to expand full configuration
require("keymaps").setup({
-- Main keybinding to open the cheatsheet (set to "" to disable)
key = "<leader>?",
-- Use telescope if available, fallback to floating window
telescope = true,
-- Show nerd font icons (requires a nerd font)
icons = true,
-- Include vim builtin keymaps
include_builtins = false,
-- Include buffer-local keymaps (from netrw, help, etc.)
-- Set to false to hide noisy internal keymaps
include_buffer_local = false,
-- Include standard Vim motions and commands (h/j/k/l, w/e/b, text objects, etc.)
-- These are merged with your custom keymaps for a complete reference
include_motions = true,
-- Enable usage tracking
track_usage = false,
-- Auto-refresh when config files change
auto_refresh = true,
-- Cache timeout in seconds (0 = no cache)
cache_timeout = 300,
-- Category patterns for auto-categorization
-- Keys are matched against these patterns to determine category
category_patterns = {
["LSP"] = {
"^g[dDrRiItT]",
"^<leader>l",
"^<leader>c[aAdDfFrRsS]",
"hover", "diagnostic", "definition", "references",
},
["Git"] = {
"^<leader>g",
"^<leader>h",
"gitsigns", "fugitive", "neogit", "lazygit",
},
["Navigation"] = {
"^<C%-[hjkl]>",
"^<leader>w",
"^<leader>b",
"buffer", "window", "split",
},
["Harpoon"] = { "harpoon", "^<leader>a" },
["Telescope"] = { "telescope", "^<leader>f", "^<leader>s" },
["File Explorer"] = { "^<leader>e", "nvim%-tree", "neo%-tree", "oil" },
["Editing"] = { "yank", "paste", "delete", "surround" },
["Comments"] = { "^gc", "^gb", "comment" },
["Debugging"] = { "dap", "debug", "breakpoint" },
["Testing"] = { "^<leader>t", "neotest", "test" },
["Terminal"] = { "terminal", "toggleterm" },
-- Add your own!
["Custom"] = { "my_pattern" },
},
-- Patterns to exclude from display
exclude_patterns = {
"^<Plug>",
"^<SNR>",
},
-- Icons for categories (requires nerd font)
category_icons = {
["LSP"] = "",
["Git"] = "",
["Navigation"] = "",
["Harpoon"] = "",
["Telescope"] = "",
["File Explorer"] = "",
["Editing"] = "",
["Comments"] = "",
["Debugging"] = "",
["Testing"] = "",
["Terminal"] = "",
["Other"] = "",
},
-- Icons for modes
mode_icons = {
n = "", -- Normal
i = "", -- Insert
v = "", -- Visual
x = "", -- Visual Block
s = "", -- Select
o = "", -- Operator
c = "", -- Command
t = "", -- Terminal
},
})require("keymaps").setup() -- That's it! Uses sensible defaults| Command | Description |
|---|---|
:Keymaps |
Open the keymaps cheatsheet |
:Keymaps LSP |
Filter by category (with tab completion!) |
:KeymapsRefresh |
Refresh the keymaps cache |
:KeymapsExport markdown |
Export to keymaps.md |
:KeymapsExport html |
Export to searchable keymaps.html |
:KeymapsExport json |
Export to keymaps.json |
:KeymapsStats |
Show usage statistics |
| Key | Action |
|---|---|
<leader>? |
Open keymaps cheatsheet |
| Key | Action |
|---|---|
<CR> |
Copy keymap to clipboard |
<C-x> |
Execute the keymap |
<Esc> |
Close |
| Key | Action |
|---|---|
q / <Esc> |
Close |
/ |
Search |
r |
Refresh |
local keymaps = require("keymaps")
-- Get all keymaps
local all = keymaps.get_keymaps()
-- Search keymaps
local results = keymaps.search("telescope")
-- Filter by category or mode
local lsp = keymaps.get_by_category("LSP")
local normal = keymaps.get_by_mode("n")
-- Get available categories
local categories = keymaps.get_categories()
-- Export
keymaps.export_to("markdown", "~/keymaps.md")
keymaps.export_to("html", "~/keymaps.html")
keymaps.export_to("json", "~/keymaps.json")
-- Open UI
keymaps.open() -- all keymaps
keymaps.open("Git") -- filtered
-- Refresh cache
keymaps.refresh()| keymaps.nvim | which-key.nvim | |
|---|---|---|
| Auto-detect keymaps | ✅ | ❌ |
| Popup on keypress | ❌ | ✅ |
| Searchable cheatsheet | ✅ | Limited |
| Export to files | ✅ | ❌ |
| Plugin source detection | ✅ | ❌ |
| Usage tracking | ✅ | ❌ |
Pro tip: Use both together! which-key shows hints as you type, keymaps.nvim gives you the full searchable reference.
| keymaps.nvim | cheatsheet.nvim | |
|---|---|---|
| Auto-detect keymaps | ✅ | Partial |
| Bundled cheatsheets | ❌ | ✅ |
| Custom cheatsheet files | ❌ | ✅ |
| HTML export with search | ✅ | ❌ |
| Smart categorization | ✅ | Limited |
Track your most used keymaps
require("keymaps").setup({
track_usage = true,
})
-- Then run :KeymapsStats to see what you actually use!Auto-export on quit
vim.api.nvim_create_autocmd("VimLeavePre", {
callback = function()
require("keymaps").export_to("markdown", "~/.config/nvim/KEYMAPS.md")
end,
})Add custom categories for AI tools
require("keymaps").setup({
category_patterns = {
["AI"] = {
"copilot",
"codeium",
"chatgpt",
"^<leader>a",
},
},
category_icons = {
["AI"] = "",
},
})Show only custom keymaps (hide builtins)
require("keymaps").setup({
include_builtins = false,
exclude_patterns = {
"^<Plug>",
"^<SNR>",
"^%w$", -- Single character keys
},
})Use with dashboard
-- For alpha.nvim or dashboard.nvim
local function get_keymap_count()
return #require("keymaps").get_keymaps()
end
-- Display: "You have 142 keymaps configured"Keymaps not showing up?
- Make sure your plugins are loaded before calling
:Keymaps - Try
:KeymapsRefreshto clear the cache - Check if keymaps are excluded by
exclude_patterns - Run
:lua print(vim.inspect(require("keymaps").get_keymaps()))to debug
Icons not displaying correctly?
Make sure you have a Nerd Font installed and configured in your terminal. Alternatively, disable icons:
require("keymaps").setup({
icons = false,
})Telescope not working?
Ensure telescope.nvim is installed and loaded. The plugin will automatically fall back to a floating window if Telescope isn't available.
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
MIT License - see LICENSE for details.
- Inspired by which-key.nvim and cheatsheet.nvim
- Thanks to the amazing Neovim community
Made with ❤️ by Abdul Hamid Achik for the Neovim community