LeetCode/NeetCode/LintCode without leaving Neovim. Browse NeetCode's roadmap or a merged catalog, solve/test locally, submit to any of the three.
- Test locally (fast) against an openleetcode checker or a sandboxed reference 'oracle' solution, falling back to the judge's own test run — which also settles problems with more than one right answer (how).
- Editable test cases (can also take from failed submissions) (more).
- C++ autocomplete sees exactly the types each problem defines, via a generated per-problem header (why).
- Statements, tests, starter code and the judge come from the first provider in a reorderable chain that can serve the problem, across all 3 providers.
- Browse NeetCode's roadmap as an ASCII DAG.
- Completions is counted from your real cloud submission history, merged across all 3 providers (how).
- Your solution is an autosaved file on disk, so LSP, treesitter, formatter and your keymaps just work.
- Neovim 0.10+ and
curl - telescope.nvim for the problem finder
python3, a C++ compiler,swiftc, orrustcfor the corresponding local test runs (python3also runs openleetcode checkers)- bubblewrap (
bwrap) on Linux or Apple's built-insandbox-execon macOS to sandbox provider-supplied reference/editorial/community oracles and checkers (your solution runs separately) - optional: image.nvim for inline diagrams
- optional: fidget.nvim for spinners
on long-running steps (opening a problem, checking other providers for a
stronger oracle) and status updates that replace in place instead of
stacking a toast per step. Detected automatically if installed — nothing to
configure on meatcode's side. Without it (or with any other notifier),
everything still works through plain
vim.notify.
Python, C++, Swift and Rust are the supported solution languages. Unsupported
problem signatures use the judge's test run. Rust needs no Cargo project
or downloaded crates; see local coverage.
For Rust IntelliSense, configure rust-analyzer and install the standard-library
sources (rust-src); MeatCode generates its non-Cargo project and judge context
automatically. See Rust editor support.
For Swift IntelliSense, enable nvim-lspconfig's SourceKit configuration in your
editor; its defaults support standalone solution files.
See Swift editor support.
lazy.nvim
{
"urwrstkn8mare/meatcode.nvim",
cmd = "MeatCode",
dependencies = {
"nvim-telescope/telescope.nvim",
"3rd/image.nvim", -- optional
},
opts = {
lang = "python", -- or "cpp", "swift", "rust"
list = "neetcode150", -- blind75 | neetcode150 | neetcode250 | allNC
},
}packer.nvim
use {
"urwrstkn8mare/meatcode.nvim",
requires = { "nvim-telescope/telescope.nvim" },
config = function() require("meatcode").setup({}) end,
}Every option: doc/configuration.md.
Browsing and opening free problems works signed out; submitting does not. Run
:MeatCode login leetcode|neetcode|lintcode and the page walks you through
getting the credential — or press <CR> on a status row of the homepage.
Credentials are written 0600 under stdpath("cache")/meatcode and only ever
sent to the service they belong to. What each provider
wants.
| Command | What it does |
|---|---|
:MeatCode |
Homepage: providers, language, catalog, progress, jumps |
:MeatCode roadmap [name] |
The topic DAG for a curated list |
:MeatCode list [query] |
Fuzzy-search the merged catalog |
:MeatCode random |
A random unsolved problem you can open |
:MeatCode daily |
LeetCode's problem of the day |
:MeatCode lang [name] |
Show or change language: python, cpp, swift, rust |
:MeatCode login/logout [provider] |
See above |
The homepage, roadmap and finder share one tab: opening any of them jumps
back to it and switches what it shows there instead of piling up tabs, and
q/<Esc> steps back through whatever you navigated through to get there.
Everything you do to a problem is a buffer-local mapping, not another Ex
command. A problem opens in its own tab: statement left, solution right,
results underneath. Only one problem is open at a time — opening another one
(from the finder, the roadmap, random, daily, …) closes the current one
first, saving its code, the same as q would.
Settings and login/logout commands update existing views immediately. Changing the language refreshes the catalogue and reopens the current problem in that language; edits are saved automatically, with no save prompt.
| Key | Action |
|---|---|
<leader>nr |
Run the test cases (locally, or on the judge's test run) |
<leader>ns |
Submit |
<leader>nt |
Edit the local test cases |
<leader>na |
Add the last failed submission input as a case |
<leader>nR |
Reset the solution to the starter code |
<leader>no |
Open a provider/solution/submissions/video link |
<leader>nc |
Reorder the provider chain; choose when the cloud oracle judges |
<CR>/<Tab> |
Open the hint, link or diagram under the cursor |
q |
Close |
Starting another test run cancels the current run and starts the replacement. Submitting during a test run cancels that run first, including its cloud test request. An in-flight submission is not replaced by another submission.
The roadmap, list and finder each advertise their own keys on screen (? on
the roadmap for the full set).
- Configuration — every option and highlight group
- Local test runs — coverage, editing cases, crash output
- C++ and clangd — the generated headers and
.clangd - Python and your language server — the auto-import block
- Progress tracking — how completions and streaks count
- Provider APIs — NeetCode, LeetCode, LintCode
:help meatcode
The headless integration checks launch real local runner processes and operate the actual Neovim UI buffers and commands:
nvim --headless -u NONE -l tests/local_runs.lua
nvim --headless -u NONE -l tests/cpp_intervals.lua
nvim --headless -u NONE -l tests/cpp_structures.lua
nvim --headless -u NONE -l tests/python_structures.lua
nvim --headless -u NONE -l tests/rust_structures.lua
nvim --headless -u NONE -l tests/swift_structures.lua
nvim --headless -u NONE -l tests/ui_state.lua
MEATCODE_NO_SETUP=1 nvim --headless -u NONE -l tests/ui_state.lua
MEATCODE_RUST_ANALYZER=/path/to/rust-analyzer nvim --headless -u NONE -l tests/rust_editor.luaThe runner check needs Python, Swift, Rust, and a supported sandbox.
The C++ interval check needs a C++23 compiler and a supported sandbox. If macOS tool shims fail inside the sandbox, select the compiler and SDK explicitly:
MEATCODE_CPP_COMPILER="$(xcrun --find clang++)" SDKROOT="$(xcrun --show-sdk-path)" \
nvim --headless -u NONE -l tests/cpp_intervals.luaUI checks fixture provider responses; they do not log into real accounts. To also
exercise the Telescope catalogue, set MEATCODE_PICKER=1,
MEATCODE_TELESCOPE to your telescope.nvim checkout, and MEATCODE_PLENARY
to your plenary.nvim checkout when running tests/ui_state.lua.
The Rust editor check additionally needs rust-analyzer and rust-src; it checks
completion, compiler diagnostics, clean solution files and isolated helper types.
- Windows Sandboxing support for local solution oracle
- Sorting and filtering in the problem list view
- Fetch LintCode beat by % metric and render memory usage in human readable text
- Notes per problem, kept beside the solution file
- A solved/attempted filter in the finder, driven by the shared history
- Add a configurable minimum number of completions to count as completed (i.e. be highlighted green by this plugin)
- Support for other notifier plugins (nvim-notify, snacks, noice) beyond fidget.nvim's optional integration (more)
All three APIs used here are undocumented and can change without notice. meatcode.nvim is not affiliated with or endorsed by NeetCode, LeetCode or LintCode; submissions run on their infrastructure, so be reasonable with them.
Fair warning: this repo is mostly the result of some careful LLM prompting. I still read every issue and PR and know the codebase well enough to maintain it for as long as I use it.
Thanks to leetcode.nvim for inspiration.
