dap-mode for Emacs: DAP debugging and Docker sessions
Emacs :heart: Debug Adapter Protocol
At a glance
- What is it?
- dap-mode connects Emacs to debug servers through the Debug Adapter Protocol, with language-specific providers and optional Docker integration. It suits Emacs users who need programmable debugging sessions, but its API remains unstable and its Docker path does not support network-connected debuggers.
- Who is it for?
- Emacs users who need a common interface across several debug adapters should evaluate dap-mode, especially if they need templates, breakpoint commands, or containerized sessions. Developers needing a stable extension API or network debugging through the Docker integration should wait or choose another client.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 126 days ago.
- What is it written in?
- Mainly Emacs Lisp, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
dap-mode's Role in an Emacs Debugging Workflow
dap-mode is an Emacs client and library for the Debug Adapter Protocol. DAP is a wire protocol for communication between a debugging client and a debug server. The README compares it with the Language Server Protocol, but assigns it a different job: instead of primarily exchanging language-service information, DAP carries operations such as launching a program, managing breakpoints, and controlling a debugging session. dap-mode places that protocol behind Emacs commands and language-specific providers.
The project is intended for developers who debug from Emacs and do not want each debugger to behave as an unrelated editor subsystem. The repository contains separate Emacs Lisp modules for C, C++, Python, Ruby, Go, JavaScript, PHP, PowerShell, LLDB, GDB, and other environments. These files indicate that coverage is organized around debug providers rather than a single universal adapter. A user still needs an appropriate debug server installed outside Emacs, but dap-mode can supply the client-side template, provider, and session integration.
The documented interaction starts with either `dap-debug` or `dap-debug-edit-template`. The first command asks for a registered template and starts that configuration using the template's default values. The second opens a declaration in a temporary buffer so its contents can be adjusted before execution. This is useful when a language has a general launch template but the current repository needs a different executable path, working directory, port, or server-specific argument.
The repository also provides `dap-hydra`, a keyboard-driven command interface available when a stopped program can be acted upon. This places common session operations in one Emacs interface rather than requiring users to memorize separate command bindings for every debug server. The README states that dap-mode is tested against Java, Python, Ruby, Elixir, and LLDB for C, C++, Objective-C, and Swift. That list is narrower than the visible set of adapter modules, so it should not be treated as a claim of equal test coverage for every provider.
From Registered Templates to Debug Server Sessions
The repository layout shows a modular architecture. `dap-mode.el` is the central package, while files such as `dap-python.el`, `dap-go.el`, `dap-codelldb.el`, `dap-js.el`, `dap-lldb.el`, and `dap-gdb.el` contain language or adapter integrations. Supporting modules handle narrower concerns: `dap-hydra.el` exposes session commands, `dap-overlays.el` handles editor display, `dap-variables.el` deals with variable inspection, and `dap-docker.el` adapts sessions to containerized debug servers.
That separation matters because DAP does not itself define every debugger's launch behavior. A debug adapter implements protocol requests, while the client supplies a registered template and starts that adapter. According to the README, `dap-debug` selects a registered debug template, while `dap-debug-edit-template` prepares a template declaration in a temporary buffer. The latter is the more deliberate path because it exposes the configuration before Emacs creates the session.
A generated template is not automatically permanent. The README instructs users to execute the buffer contents with `C-M-x` for the changes to take effect, and to copy the declaration into their Emacs configuration if it should persist. This workflow has two consequences. First, editing a template and running it are separate actions. Second, maintaining a repeatable setup means storing the finalized declaration in the Emacs configuration rather than relying on an unrecorded temporary buffer.
The project also exposes a stopped hook. Registering `dap-stopped-hook` can invoke `dap-hydra` whenever execution reaches a breakpoint or another stopped state. This allows the hydra to appear automatically when the debug session needs attention. The repository includes a `CHANGELOG.org` and a `docs/` directory, but the README does not describe a schema migration or compatibility policy for user configurations. Given the stated unstable API, existing configuration snippets should be checked against the corresponding documentation when the package changes.
Installing dap-mode and Preparing Automatic Breakpoint Controls
The README provides MELPA and stable MELPA package badges, so the documented distribution route is package installation through MELPA or stable MELPA. It does not give an exact Emacs configuration file for adding the archive, package installation command, or initialization expression, so those commands should not be invented here. Once dap-mode is available through the reader's chosen MELPA setup, a real first action can be automatic presentation of the debugging hydra.
Add the hook in the Emacs configuration to call `dap-hydra` interactively whenever `dap-stopped-hook` runs. The following is the exact example printed in the README:
(add-hook 'dap-stopped-hook
(lambda (arg) (call-interactively #'dap-hydra)))After Emacs reloads the configuration, the hook is registered. A later debug session that invokes the stopped hook should call the hydra. This example does not create a debug template or install a debug server, so it is a session-control setup rather than a complete first program launch. For program launching, the README directs users to the registered `dap-debug` entry point and the editable `dap-debug-edit-template` flow.
For source checkout development, the repository Makefile defines packaging, compilation, and test targets. It expects `eask`, with `EMACS` available as an optional override. The complete test target installs development dependencies and invokes `ert-runner`:
Run the Makefile's `test` target.
The command expands to `eask install-deps --dev` and `eask exec ert-runner -L.`. Its success depends on the reader having the expected Eask and Emacs environment. The repository does not document operating system prerequisites in the README. Development users should therefore treat the Makefile targets as a separate path from the MELPA distribution route, not assume that a normal package installation requires Eask.
Dap-Mode Docker Configuration and Its Network Boundary
dap-mode can adapt a normal debug provider so that the debug server runs inside Docker. The README identifies `dap-docker-register` as the main integration function. It finds the original debug template, patches it, registers a debug provider, reads configuration, and combines that configuration with defaults. Users can place settings in `.dir-locals` or in `.lsp-docker.yml`. The same Docker mechanism is associated with the related `lsp-docker` project.
The documented `.lsp-docker.yml` structure has an `lsp` mapping for source paths and a `debug` section. Docker is the only supported debug `type`, while `subtype` can be `image` or `container`. The `name` can identify the image or container, and omitted names fall back to the image configured in the `lsp-docker` server section. A provider and template supply the default language integration. `launch_command` can replace the command supplied by the provider, which is relevant when a debugger executable lives somewhere other than the default location.
The source and destination mapping has a specific purpose. `/your/host/source/path` identifies the source tree from the host, while `/your/local/path/inside/a/container` identifies its corresponding path inside the container. That mapping allows source references produced by a debug server in the container to correspond to files opened in Emacs.
The important constraint is explicit in the README: the Docker mode does not currently work with a network connection to debuggers. The documentation points users who still need network communication to the `launch-args` patching performed by `dap-docker--dockerize-start-file-args`, suggesting that `nil` may need to be assigned to `dap-server-path` before session creation. That is an advanced workaround described by the project, not a documented plug-and-play network setting.
Docker also does not remove the requirement to choose a working default configuration. The README specifically says that its default configuration does not provide sensible debugging defaults. An image containing the debugger may still fail if its template, executable path, source mount, or launch command does not match the repository. Containerized debugging is therefore useful for repeatable environments, but it adds configuration surfaces rather than making sessions portable by default.
Provider Coverage, Release History, and Extension Cost
The top-level files show broad adapter availability, including `dap-cpptools.el`, `dap-codelldb.el`, `dap-dlv-go.el`, `dap-node.el`, `dap-python.el`, `dap-ruby.el`, `dap-php.el`, `dap-pwsh.el`, `dap-firefox.el`, `dap-unity.el`, and others. The topics listed for the repository also cover several programming languages. However, topic labels and source files do not establish that every adapter is current, equally supported, or tested against the same server versions.
The README states that the API is unstable until a 1.0 release. That is a direct maintenance and extension warning. Users who only invoke the documented commands still depend on configuration syntax, while package authors and users of internal functions face a greater upgrade cost because compatibility guarantees are not claimed. The Docker documentation itself demonstrates the sensitivity of this area by referring to internal patching functions and detailed template fields.
The release history lists version 0.8 on 2024-04-06, version 0.7 on 2021-09-04, and version 0.6 on 2020-08-07. The repository is not archived, and its last push was on 2026-06-19. Those facts show recent repository activity, but they do not erase the pre-1.0 API warning or prove that every adapter is actively maintained. Upgrade planning should account for gaps between releases and for adapter-specific dependencies.
The package is licensed under GPL-3.0. That identifier defines the stated licensing basis for redistribution and modification, but this review does not provide legal advice. Organizations with formal license-review processes should examine the repository `LICENSE` file and their distribution model. The cost of adopting dap-mode is therefore not limited to Emacs configuration: a team may also need to install debug servers, create templates, verify path mappings, and adapt customization when APIs change before 1.0.
Choosing dap-mode Instead of Adapter-Specific Debugging
The real alternative is to configure each language's native or editor-specific debugging client independently. For example, an Emacs user might interact with a language-specific command or extension that knows that debugger's launch and breakpoint conventions without exposing a common DAP template interface. The difference is not that dap-mode supports more debugging concepts. The difference is the client layer: dap-mode standardizes session handling around DAP while delegating language behavior to debug servers and providers.
This approach is useful when several debug adapters are already installed and the user wants one `dap-debug` workflow across them. The editable template also offers a persistent, inspectable declaration instead of relying only on hidden defaults. `dap-hydra` adds a common stopping-state interface, and `dap-docker-register` can transform a provider setup for a containerized server.
Adapter-specific debugging can be the better choice when its configuration model already matches the project and its editor integration is the required interface. Choosing one debugger directly avoids the pre-1.0 extension API and the possible mismatch between dap-mode templates and a server's expected configuration. It can also avoid the unsupported Docker-to-network-debugger case, although the alternative tool must separately support that deployment.
dap-mode is the wrong choice when the required language has no matching provider or when the intended debug server cannot satisfy its template. It is also a poor fit for users who need the Docker helper to connect through the network and do not want to apply the documented `launch-args` workaround. Finally, teams that require a stable extension API should not treat the current project status as a maturity guarantee. The decision should be based on an actual provider and launch template, not on the number of adapter files in the repository.
Editorial conclusion
Emacs users who need a common interface across several debug adapters should evaluate dap-mode, especially if they need templates, breakpoint commands, or containerized sessions. Developers needing a stable extension API or network debugging through the Docker integration should wait or choose another client. Verify first that your language has a matching provider, that the required debug server is installed, and that the exact launch template behaves correctly in your project.
Frequently asked questions
How do I install dap-mode for Emacs?
The README provides package links for MELPA and stable MELPA but does not document the archive configuration or exact installation command. It also documents a Makefile test target for source development using Eask.
How do I start debugging a project with dap-mode?
Use `dap-debug` to select a registered template, or use `dap-debug-edit-template` to edit a template declaration before running it. Changes from the temporary template buffer take effect after executing the code with `C-M-x`.
Can dap-mode open the hydra automatically at a breakpoint?
Yes. The README shows an entry for `dap-stopped-hook` that calls `dap-hydra` interactively whenever the stopped hook runs.
Does dap-mode support remote debuggers through Docker?
Not through its current Docker integration. The README explicitly says that this part is not implemented and points to `launch-args` patching by `dap-docker--dockerize-start-file-args` for advanced workarounds.
Is the dap-mode API stable?
No stable status is claimed. The README says that the API is unstable until a 1.0 release, so extension and configuration code may require additional verification during upgrades.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/emacs-lsp-dap-mode)Was this useful?