Zero-config debugging for Neovim. A thin layer over
nvim-dap that reads your project and
wires up the debugger for you — no launch.json, no per-language boilerplate.
Press your debug key and pick a target.
What a per-language debug plugin does for one language, autodap orchestrates for all of them — automatically, from your project.

Open a file, set a breakpoint, press <F5>, pick a target. Nothing language-specific is
typed — the same three keys do the same thing in every project below.
C++ — executable discovered from the CMake build directory:

A lone .c file — no build system, no git repo; compiled with -g on launch:

Node — npm scripts discovered alongside the current file:

nvim-dap is powerful but ships no configuration per language: you write the
adapter and the launch config yourself, for every project. autodap fills that gap
by detecting the project from the files already in it and generating the adapter
and configurations on the fly.
launch.json and hand-written configs instead of overwriting.tsx/ts-node and virtualenvs resolve through hoisted layouts..js,
.py, or .c with no project still gets a launch config.| Language | Adapter | Discovered automatically |
|---|---|---|
| Node / JS / TS | js-debug-adapter |
every script in the nearest package.json; launch current file (uses local tsx/ts-node for TS); attach to a process |
| Python | debugpy |
launch current file (with/without args); interpreter from VIRTUAL_ENV or the nearest .venv walking up; attach on 127.0.0.1:5678 |
| C / C++ | codelldb |
executable targets from the CMake File API (bounded scan fallback); auto-compiles a lone .c/.cpp with -g when there is no build system |
PATH.With lazy.nvim:
{
'JarnDev/autodap.nvim',
dependencies = {
'mfussenegger/nvim-dap',
'williamboman/mason.nvim', -- optional
},
config = function()
require('autodap').setup()
-- Map your debug key to the friendly entrypoint:
vim.keymap.set('n', '<F5>', function() require('autodap').continue() end)
end,
}
Open a file in a supported project, press <F5>, pick a target. That's it.
setup() works with no arguments. These are the defaults:
require('autodap').setup({
-- Lazy / on-demand install: the adapter for a language is fetched via mason the
-- first time you debug that language, not at startup (mirrors mason-lspconfig's
-- `automatic_installation`). Set false to only ever use adapters on your PATH.
auto_install = true,
-- Languages to handle. Drop one to leave its filetypes entirely to your own config.
languages = { 'node', 'python', 'cpp' },
cpp = {
adapter = 'codelldb',
-- Directories scanned for prebuilt executables (globs allowed).
build_dirs = { 'build', 'cmake-build-*', 'out/build/*', 'builddir', 'out' },
-- Compile a lone .c/.cpp with -g when there is no build system to find a
-- binary in. Set false to be prompted for an executable path instead.
auto_compile = true,
compile_flags = { '-g', '-O0' },
},
-- Extra CLI args appended to the "debug the test under the cursor" command,
-- per framework. Escape hatch for version-specific flags — e.g. vitest may
-- need { '--no-file-parallelism' } (or an older single-thread flag) for
-- breakpoints to bind reliably.
test = {
extra_args = { jest = {}, vitest = {}, pytest = {} },
},
})
Map your debug key to require('autodap').continue() and use it as you would
dap.continue(). It does one extra thing on a fresh machine: it checks the
adapter is installed before starting and kicks off the mason install with a
notification, instead of letting nvim-dap throw a stack trace on a missing
binary. Run it again once the install finishes.
A plain require('dap').continue() from your existing keymaps also works — the
generated configs come through the provider — it just skips that install guard.
The large-project support is additive: it never gates basic debugging. Open a
loose .js or .py with no package.json, no virtualenv, not even a git repo,
and you still get a Launch current file config; the root falls back to the
file's own directory. A project only adds targets (npm scripts, CMake
executables) on top.
C/C++ works too — a native debugger can't run a .c directly, so when there
is no build system autodap compiles the current file with -g and debugs the
result, recompiling on each launch so edits are always picked up.
Put the cursor in a test and run it in the debugger — jest, vitest, or pytest, detected from the project:
vim.keymap.set('n', '<leader>dt', function() require('autodap').debug_test() end)
It finds the nearest test above the cursor (it/test/describe for JS,
def test_* and its enclosing class for pytest) and launches just that test.
The same entry also shows up at the top of the <F5> picker when you're in a
test file. If breakpoints don't bind on a given framework version, add flags via
test.extra_args.
:AutodapContinue — same as require('autodap').continue().:AutodapTest — debug the test under the cursor.:AutodapReset — forget the remembered C/C++ executable for the current project.<F5> on a fresh machine
starts the download and asks you to run again once it lands. It does not block
and auto-continue (yet — see roadmap).--runInBand; vitest
breakpoints may need a single-thread flag depending on the version) — use
test.extra_args to tune. Nearest-test detection is regex-based, not Treesitter.pkg:once('install:success')).Config generation and target discovery are exercised headless against fixture projects (a node monorepo, python venvs, CMake projects with and without a File API reply, and single-file compilation):
make test
The first run clones nvim-dap into tests/.deps/ so the tests hit the real
provider and adapter API.
:help autodap — the full docs (generated from this README).:checkhealth autodap — verifies Neovim, nvim-dap and mason, shows which
adapters are installed, and prints what autodap detects for the current buffer
(language, project root, C/C++ targets, the test under the cursor). Run it
first when something isn't picked up.autodap is generic on purpose. If you only ever debug one language, a dedicated plugin may fit you better (autodap does not install or depend on these — they're alternatives, not requirements):
Built entirely on nvim-dap and mason.nvim. mason-nvim-dap is a great companion — it installs debug adapters; autodap generates the configurations you would otherwise write by hand.