Repository: go-delve/delve
Pull request #2846 (2021-12-28 23:52:15)

dap: support 'Env' attribute for launch requests
Env is applied in addition to the delve process environment
variables. The env setting is done by calling `os.Setenv`
as early as possible when a Launch request is received.

Prior discussion is in https://github.com/go-delve/delve/pull/2582

In Visual Studio Code, setting null for an environment variable
in launch.json or tasks.json indicates users want to unset
the environment variable. Support the behavior by accepting
nil value.

Updates golang/vscode-go#1978


Patch:
diff --git a/Documentation/api/README.md b/Documentation/api/README.md
index 916b7390..c98e3c78 100644
--- a/Documentation/api/README.md
+++ b/Documentation/api/README.md
@@ -1,20 +1,20 @@
-# API Documentation
+# Server/Client API Documentation
 
-Delve exposes an API interface so that other programs, mostly IDEs and editors, can interact with Delve programmatically. The API is used by the terminal client, so will always stay up to date in lockstep regardless of new features.
+Delve exposes two API interfaces, JSON-RPC and DAP, so that frontends other than the built-in [terminal client](../cli/README.md), such as [IDEs and editors](../EditorIntegration.md), can interact with Delve programmatically. The [JSON-RPC API](json-rpc/README.md) is used by the [terminal client](../cli/README.md), and will always stay up to date in lockstep regardless of new features. The [DAP API](dap/README.md) is a popular generic API already in use by many [tools](https://microsoft.github.io/debug-adapter-protocol/implementors/tools/).
 
 ## Usage
 
 In order to run Delve in "API mode", simply invoke with one of the standard commands, providing the `--headless` flag, like so:
 
 ```
-$ dlv debug --headless --api-version=2 --log --listen=127.0.0.1:8181
+$ dlv debug --headless --api-version=2 --log --log-output=debugger,dap,rpc --listen=127.0.0.1:8181
 ```
 
-This will start the debugger in a non-interactive mode, listening on the specified address, and will enable logging. The last two flags are optional, of course.
+This will start the debugger in a non-interactive mode, listening on the specified address, and will enable logging. The logging flags as well as the server address are optional, of course.
 
-Optionally, you may also specify the `--accept-multiclient` flag if you would like to connect multiple clients to the API.
+Optionally, you may also specify the `--accept-multiclient` flag if you would like to connect multiple JSON-RPC or DAP clients to the API.
 
-You can connect the headless debugger from Delve itself using the `connect` subcommand:
+You can connect to the headless debugger from Delve itself using the `connect` subcommand:
 
 ```
 $ dlv connect 127.0.0.1:8181
@@ -29,3 +29,4 @@ Delve has been architected in such a way as to allow multiple client/server impl
 ### Current API Interfaces
 
 - [JSON-RPC](json-rpc/README.md)
+- [DAP](dap/README.md)
diff --git a/Documentation/api/dap/README.md b/Documentation/api/dap/README.md
new file mode 100644
index 00000000..a03b5955
--- /dev/null
+++ b/Documentation/api/dap/README.md
@@ -0,0 +1,116 @@
+# DAP Interface
+
+Delve exposes a [DAP](https://microsoft.github.io/debug-adapter-protocol/overview) API interface.
+
+This interface is served over a streaming TCP socket using `dlv` server in one of the two headless modes:
+* `dlv dap` - starts a single-use DAP-only server that waits for a client to specify launch/attach configuration for starting the debug session.
+* `dlv --headless <command> <debugee>` - starts a general server, enters a debug session for the specified debuggee and waits for a [JSON-RPC](../json-rpc/README.md) or a [DAP](https://microsoft.github.io/debug-adapter-protocol/overview) client to begin interactive debugging. Can be used in multi-client mode with the following options:
+   *  `--accept-multiclient` - use to support connections from multiple clients
+   *  `--continue` - use to resume debuggee execution as soon as server session starts
+
+The primary user of this mode is [VS Code Go](https://github.com/golang/vscode-go). Please see its 
+detailed [debugging documentation](https://github.com/golang/vscode-go/blob/master/docs/debugging.md) for additional information.
+
+## Debug Adapter Protocol
+
+[DAP](https://microsoft.github.io/debug-adapter-protocol/specification) is a general debugging protocol supported by many [tools](https://microsoft.github.io/debug-adapter-protocol/implementors/tools/) and [programming languages](https://microsoft.github.io/debug-adapter-protocol/implementors/adapters/). We tailored it to Go specifics, such as mapping [threads request](https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Threads) to communicate goroutines and [exceptionInfo request](https://microsoft.github.io/debug-adapter-protocol/specification#Requests_ExceptionInfo) to support panics and fatal errors.
+
+See [dap.Server.handleRequest](https://github.com/go-delve/delve/search?q=handleRequest) and capabilities set in [dap.Server.onInitializeRequest](https://github.com/go-delve/delve/search?q=onInitializeRequest) for an up-to-date list of supported requests and options.
+
+## Launch and Attach Configurations
+
+In addition to the general [DAP spec](https://microsoft.github.io/debug-adapter-protocol/specification), the server supports the following implementation-specific configuration options for starting the debug session:
+   * [AttachRequestArguments](https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Attach) - see [AttachConfig godoc](https://pkg.go.dev/github.com/go-delve/delve/service/dap#AttachConfig)
+   * [LaunchRequestArguments](https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Launch) - see [LaunchConfig godoc](https://pkg.go.dev/github.com/go-delve/delve/service/dap#LaunchConfig)
+
+Not all of the configurations are supported by each of the two available DAP servers:
+
+<table border=1>
+<tr>
+<th>request<th>"mode":<th>`dlv dap`<th>`dlv --headless`
+</tr>
+<tr>
+<td>launch<td>"debug"<br>"test"<br>"exec"<br>...<td>supported<td>NOT supported
+<tr>
+<td>attach<td>"local"<td>supported<td>NOT supported
+</tr>
+<tr>
+<td>attach<td>"remote"<td>NOT supported<td>supported
+</tr>
+</table>
+
+## Disconnect and Shutdown
+
+### Single-Client Mode
+
+When used with `dlv dap` or `dlv --headless --accept-multiclient=false` (default), the DAP server will shut itself down at the end of the debug session, when the client sends a [disconnect request](https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Disconnect). If the debuggee was launched, it will be taken down as well. If the debugee was attached to, `terminateDebuggee` option will be respected.
+
+When the program terminates, we send a [terminated event](https://microsoft.github.io/debug-adapter-protocol/specification#Events_Terminated), which is expected to trigger a [disconnect request](https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Disconnect) from the client for a session and a server shutdown. The [restart request](https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Restart) is not yet supported. 
+
+The server also shuts down in case of a client connection error or SIGTERM signal, taking down a launched process, but letting an attached process continue. 
+
+Pressing Ctrl-C on the terminal where a headless server is running sends SIGINT to the debuggee, foregrounded in headless mode to support debugging interactive programs.
+
+### Multi-Client Mode
+
+When used with `dlv --headless --accept-multiclient=true`, the DAP server will honor the multi-client mode when a client [disconnects](https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Disconnect)) or client connection fails. The server will remain running and ready for a new client connection, and the debuggee will remain in whatever state it was at the time of disconnect - running or halted. Once [`suspendDebuggee`](https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Disconnect) option is supported by frontends like VS Code ([vscode/issues/134412](https://github.com/microsoft/vscode/issues/134412)), we will update the server to offer this as a way to specify debuggee state on disconnect.
+
+The client may request full shutdown of the server and the debuggee with [`terminateDebuggee`](https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Disconnect) option.
+
+The server shuts down in response to a SIGTERM signal, taking down a launched process, but letting an attached process continue.
+
+Pressing Ctrl-C on the terminal where a headless server is running sends SIGINT to the debuggee, foregrounded in headless mode to support debugging interactive programs.
+
+## Debugger Output
+
+The debugger always logs one of the following on start-up to stdout:
+* `dlv dap`:
+   * `DAP server listening at: <host>:<port>`
+* `dlv --headless`: 
+   * `API server listening at: <host>:<port>`
+
+This can be used to confirm that server start-up succeeded.
+
+The server uses [output events](https://microsoft.github.io/debug-adapter-protocol/specification#Events_Output) to communicate errors and select status messages to the client. For example:
+
+```
+Step interrupted by a breakpoint. Use 'Continue' to resume the original step command.
+invalid command: Unable to step while the previous step is interrupted by a breakpoint.
+Use 'Continue' to resume the original step command.
+Detaching and terminating target process
+```
+
+More detailed logging can be enabled with `--log --log-output=dap` as part of the [`dlv` command](../../usage/dlv.md).
+It will record the server-side DAP message traffic. For example, 
+```
+2022-01-04T00:27:57-08:00 debug layer=dap [<- from client]{"seq":1,"type":"request","command":"initialize","arguments":{"clientID":"vscode","clientName":"Visual Studio Code","adapterID":"go","locale":"en-us","linesStartAt1":true,"columnsStartAt1":true,"pathFormat":"path","supportsVariableType":true,"supportsVariablePaging":true,"supportsRunInTerminalRequest":true,"supportsMemoryReferences":true,"supportsProgressReporting":true,"supportsInvalidatedEvent":true}}
+2022-01-04T00:27:57-08:00 debug layer=dap [-> to client]{"seq":0,"type":"response","request_seq":1,"success":true,"command":"initialize","body":{"supportsConfigurationDoneRequest":true,"supportsFunctionBreakpoints":true,"supportsConditionalBreakpoints":true,"supportsEvaluateForHovers":true,"supportsSetVariable":true,"supportsExceptionInfoRequest":true,"supportTerminateDebuggee":true,"supportsDelayedStackTraceLoading":true,"supportsLogPoints":true,"supportsDisassembleRequest":true,"supportsClipboardContext":true,"supportsSteppingGranularity":true,"supportsInstructionBreakpoints":true}}
+2022-01-04T00:27:57-08:00 debug layer=dap [<- from client]{"seq":2,"type":"request","command":"launch","arguments":{"name":"Launch file","type":"go","request":"launch","mode":"debug","program":"./temp.go","hideSystemGoroutines":true,"__buildDir":"/Users/polina/go/src","__sessionId":"2ad0f0c1-a1fd-4fff-9fff-b8bc9a933fe5"}}
+2022-01-04T00:27:57-08:00 debug layer=dap parsed launch config: {
+	"mode": "debug",
+	"program": "./temp.go",
+	"backend": "default",
+	"stackTraceDepth": 50,
+	"hideSystemGoroutines": true
+}
+...
+```
+This logging is written to stderr and is not forwarded via 
+[output events](https://microsoft.github.io/debug-adapter-protocol/specification#Events_Output).
+
+## Debuggee Output
+
+Debuggee's stdout and stderr are written to stdout and stderr respectfully and are not forwarded via 
+[output events](https://microsoft.github.io/debug-adapter-protocol/specification#Events_Output).
+
+## Versions
+
+The initial DAP support was released in v1.6.1 with many additional improvements in subsequent versions. The [remote attach](https://github.com/go-delve/delve/issues/2328) support was added in v1.7.3.
+
+The DAP API changes are backward-compatible as all new features are opt-in only. To update to a new [DAP version](https://microsoft.github.io/debug-adapter-protocol/changelog) and import a new DAP feature into delve, 
+one must first update the [go-dap](https://github.com/google/go-dap) dependency.
+
+<!--- TODO:
+- most requests are handled synchronously and block
+- hence many commands not supported when running, but setting breakpoints is
+--->
\ No newline at end of file
diff --git a/Documentation/cli/README.md b/Documentation/cli/README.md
index 53f6c84a..951a94c9 100644
--- a/Documentation/cli/README.md
+++ b/Documentation/cli/README.md
@@ -104,9 +104,9 @@ If regex is specified only function arguments with a name matching it will be re
 ## break
 Sets a breakpoint.
 
-	break [name] <linespec>
+	break [name] [linespec]
 
-See [Documentation/cli/locspec.md](//github.com/go-delve/delve/tree/master/Documentation/cli/locspec.md) for the syntax of linespec.
+See [Documentation/cli/locspec.md](//github.com/go-delve/delve/tree/master/Documentation/cli/locspec.md) for the syntax of linespec. If linespec is omitted a breakpoint will be set on the current line.
 
 See also: "help on", "help cond" and "help clear"
 
@@ -628,9 +628,9 @@ toggle <breakpoint name or id>
 ## trace
 Set tracepoint.
 
-	trace [name] <linespec>
+	trace [name] [linespec]
 
-A tracepoint is a breakpoint that does not stop the execution of the program, instead when the tracepoint is hit a notification is displayed. See [Documentation/cli/locspec.md](//github.com/go-delve/delve/tree/master/Documentation/cli/locspec.md) for the syntax of linespec.
+A tracepoint is a breakpoint that does not stop the execution of the program, instead when the tracepoint is hit a notification is displayed. See [Documentation/cli/locspec.md](//github.com/go-delve/delve/tree/master/Documentation/cli/locspec.md) for the syntax of linespec. If linespec is omitted a tracepoint will be set on the current line.
 
 See also: "help on", "help cond" and "help clear"
 
diff --git a/Documentation/usage/README.md b/Documentation/usage/README.md
index 3bc7c5b0..851fda7b 100644
--- a/Documentation/usage/README.md
+++ b/Documentation/usage/README.md
@@ -1,5 +1,35 @@
 # Using Delve
 
-You can invoke Delve in multiple ways, depending on your usage needs. Delve makes every attempt to be user-friendly, ensuring the user has to do the least amount of work possible to begin debugging their program.
+You can invoke Delve in [multiple ways](dlv.md), depending on your usage needs. Delve makes every attempt to be user-friendly, ensuring the user has to do the least amount of work possible to begin debugging their program.
 
-Refer to the [main usage document](dlv.md) to further explore commands.
+The [available commands](dlv.md) can be grouped into the following categories:
+
+*  Specify target and start debugging with the default [terminal interface](../cli/README.md):
+   * [dlv debug [package]](dlv_debug.md)
+   * [dlv test [package]](dlv_test.md)
+   * [dlv exec \<exe\>](dlv_exec.md)
+   * [dlv attach \<pid\>](dlv_attach.md)
+   * [dlv core \<exe\> \<core\>](dlv_core.md)
+   * [dlv replay \<rr trace\> ](dlv_replay.md)
+* Trace target program execution
+   * [dlv trace [package] \<regexp\>](dlv_trace.md)
+* Start a headless backend server only and connect with an external [frontend client](../EditorIntegration.md):
+   * [dlv **--headless** \<command\> \<target\> \<args\> ](../api/ClientHowto.md#spawning-the-backend)
+      * starts a server, enters a debug session for the specified target and waits to accept a client connection over JSON-RPC or DAP
+      * `<command>` can be any of `debug`, `test`, `exec`, `attach`, `core` or `replay`
+      * if `--headless` flag is not specified the default [terminal client](../cli/README.md) will be automatically started instead
+      * compatible with [dlv connect](dlv_connect.md), [VS Code Go](https://github.com/golang/vscode-go/blob/master/docs/debugging.md#remote-debugging), [GoLand](https://www.jetbrains.com/help/go/attach-to-running-go-processes-with-debugger.html#attach-to-a-process-on-a-remote-machine)
+   * [dlv dap](dlv_dap.md)
+      * starts a DAP-only server and waits for a DAP client connection to specify the target and arguments
+      * compatible with [VS Code Go](https://github.com/golang/vscode-go/blob/master/docs/debugging.md#remote-debugging)
+      * NOT compatible with [dlv connect](dlv_connect.md), [GoLand](https://www.jetbrains.com/help/go/attach-to-running-go-processes-with-debugger.html#attach-to-a-process-on-a-remote-machine)
+   * [dlv connect \<addr\>](dlv_connect.md)
+      * starts a [terminal interface client](../cli/README.md) and connects it to a running headless server over JSON-RPC
+* Help information
+   * [dlv help [command]](dlv.md)
+   * [dlv log](dlv_log.md)
+   * [dlv backend](dlv_backend.md)
+   * [dlv redirect](dlv_redirect.md)
+   * [dlv version](dlv_version.md)
+
+The above list may be incomplete. Refer to the auto-generated [complete usage document](dlv.md) to further explore all available commands.
diff --git a/Documentation/usage/dlv.md b/Documentation/usage/dlv.md
index 7ec447aa..5e75d2a3 100644
--- a/Documentation/usage/dlv.md
+++ b/Documentation/usage/dlv.md
@@ -18,14 +18,14 @@ Pass flags to the program you are debugging using `--`, for example:
 ### Options
 
 ```
-      --accept-multiclient               Allows a headless server to accept multiple client connections.
+      --accept-multiclient               Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
       --allow-non-terminal-interactive   Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
-      --api-version int                  Selects API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
+      --api-version int                  Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
       --backend string                   Backend selection (see 'dlv help backend'). (default "default")
       --build-flags string               Build flags, to be passed to the compiler. For example: --build-flags="-tags=integration -mod=vendor -cover -v"
       --check-go-version                 Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)
       --disable-aslr                     Disables address space randomization
-      --headless                         Run debug server only, in headless mode.
+      --headless                         Run debug server only, in headless mode. Server will accept both JSON-RPC or DAP client connections.
   -h, --help                             help for dlv
       --init string                      Init file, executed by the terminal client.
   -l, --listen string                    Debugging server listen address. (default "127.0.0.1:0")
@@ -40,9 +40,9 @@ Pass flags to the program you are debugging using `--`, for example:
 ### SEE ALSO
 
 * [dlv attach](dlv_attach.md)	 - Attach to running process and begin debugging.
-* [dlv connect](dlv_connect.md)	 - Connect to a headless debug server.
+* [dlv connect](dlv_connect.md)	 - Connect to a headless debug server with a terminal client.
 * [dlv core](dlv_core.md)	 - Examine a core dump.
-* [dlv dap](dlv_dap.md)	 - [EXPERIMENTAL] Starts a headless TCP server communicating via Debug Adaptor Protocol (DAP).
+* [dlv dap](dlv_dap.md)	 - Starts a headless TCP server communicating via Debug Adaptor Protocol (DAP).
 * [dlv debug](dlv_debug.md)	 - Compile and begin debugging main package in current directory, or the package specified.
 * [dlv exec](dlv_exec.md)	 - Execute a precompiled binary, and begin a debug session.
 * [dlv replay](dlv_replay.md)	 - Replays a rr trace.
diff --git a/Documentation/usage/dlv_attach.md b/Documentation/usage/dlv_attach.md
index b98d0fd8..3b9c22de 100644
--- a/Documentation/usage/dlv_attach.md
+++ b/Documentation/usage/dlv_attach.md
@@ -25,14 +25,14 @@ dlv attach pid [executable] [flags]
 ### Options inherited from parent commands
 
 ```
-      --accept-multiclient               Allows a headless server to accept multiple client connections.
+      --accept-multiclient               Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
       --allow-non-terminal-interactive   Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
-      --api-version int                  Selects API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
+      --api-version int                  Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
       --backend string                   Backend selection (see 'dlv help backend'). (default "default")
       --build-flags string               Build flags, to be passed to the compiler. For example: --build-flags="-tags=integration -mod=vendor -cover -v"
       --check-go-version                 Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)
       --disable-aslr                     Disables address space randomization
-      --headless                         Run debug server only, in headless mode.
+      --headless                         Run debug server only, in headless mode. Server will accept both JSON-RPC or DAP client connections.
       --init string                      Init file, executed by the terminal client.
   -l, --listen string                    Debugging server listen address. (default "127.0.0.1:0")
       --log                              Enable debugging server logging.
diff --git a/Documentation/usage/dlv_backend.md b/Documentation/usage/dlv_backend.md
index 009f4094..3ccc9ba9 100644
--- a/Documentation/usage/dlv_backend.md
+++ b/Documentation/usage/dlv_backend.md
@@ -23,14 +23,14 @@ are:
 ### Options inherited from parent commands
 
 ```
-      --accept-multiclient               Allows a headless server to accept multiple client connections.
+      --accept-multiclient               Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
       --allow-non-terminal-interactive   Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
-      --api-version int                  Selects API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
+      --api-version int                  Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
       --backend string                   Backend selection (see 'dlv help backend'). (default "default")
       --build-flags string               Build flags, to be passed to the compiler. For example: --build-flags="-tags=integration -mod=vendor -cover -v"
       --check-go-version                 Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)
       --disable-aslr                     Disables address space randomization
-      --headless                         Run debug server only, in headless mode.
+      --headless                         Run debug server only, in headless mode. Server will accept both JSON-RPC or DAP client connections.
       --init string                      Init file, executed by the terminal client.
   -l, --listen string                    Debugging server listen address. (default "127.0.0.1:0")
       --log                              Enable debugging server logging.
diff --git a/Documentation/usage/dlv_connect.md b/Documentation/usage/dlv_connect.md
index 096e57e4..266e3cce 100644
--- a/Documentation/usage/dlv_connect.md
+++ b/Documentation/usage/dlv_connect.md
@@ -1,10 +1,10 @@
 ## dlv connect
 
-Connect to a headless debug server.
+Connect to a headless debug server with a terminal client.
 
 ### Synopsis
 
-Connect to a running headless debug server.
+Connect to a running headless debug server with a terminal client.
 
 ```
 dlv connect addr [flags]
@@ -19,14 +19,14 @@ dlv connect addr [flags]
 ### Options inherited from parent commands
 
 ```
-      --accept-multiclient               Allows a headless server to accept multiple client connections.
+      --accept-multiclient               Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
       --allow-non-terminal-interactive   Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
-      --api-version int                  Selects API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
+      --api-version int                  Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
       --backend string                   Backend selection (see 'dlv help backend'). (default "default")
       --build-flags string               Build flags, to be passed to the compiler. For example: --build-flags="-tags=integration -mod=vendor -cover -v"
       --check-go-version                 Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)
       --disable-aslr                     Disables address space randomization
-      --headless                         Run debug server only, in headless mode.
+      --headless                         Run debug server only, in headless mode. Server will accept both JSON-RPC or DAP client connections.
       --init string                      Init file, executed by the terminal client.
   -l, --listen string                    Debugging server listen address. (default "127.0.0.1:0")
       --log                              Enable debugging server logging.
diff --git a/Documentation/usage/dlv_core.md b/Documentation/usage/dlv_core.md
index cb69b87e..51a2c334 100644
--- a/Documentation/usage/dlv_core.md
+++ b/Documentation/usage/dlv_core.md
@@ -25,14 +25,14 @@ dlv core <executable> <core> [flags]
 ### Options inherited from parent commands
 
 ```
-      --accept-multiclient               Allows a headless server to accept multiple client connections.
+      --accept-multiclient               Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
       --allow-non-terminal-interactive   Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
-      --api-version int                  Selects API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
+      --api-version int                  Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
       --backend string                   Backend selection (see 'dlv help backend'). (default "default")
       --build-flags string               Build flags, to be passed to the compiler. For example: --build-flags="-tags=integration -mod=vendor -cover -v"
       --check-go-version                 Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)
       --disable-aslr                     Disables address space randomization
-      --headless                         Run debug server only, in headless mode.
+      --headless                         Run debug server only, in headless mode. Server will accept both JSON-RPC or DAP client connections.
       --init string                      Init file, executed by the terminal client.
   -l, --listen string                    Debugging server listen address. (default "127.0.0.1:0")
       --log                              Enable debugging server logging.
diff --git a/Documentation/usage/dlv_dap.md b/Documentation/usage/dlv_dap.md
index a929c692..b76fbe1f 100644
--- a/Documentation/usage/dlv_dap.md
+++ b/Documentation/usage/dlv_dap.md
@@ -1,22 +1,24 @@
 ## dlv dap
 
-[EXPERIMENTAL] Starts a headless TCP server communicating via Debug Adaptor Protocol (DAP).
+Starts a headless TCP server communicating via Debug Adaptor Protocol (DAP).
 
 ### Synopsis
 
-[EXPERIMENTAL] Starts a headless TCP server communicating via Debug Adaptor Protocol (DAP).
+Starts a headless TCP server communicating via Debug Adaptor Protocol (DAP).
 
-The server is always headless and requires a DAP client like vscode to connect and request a binary
-to be launched or process to be attached to. The following modes can be specified via client's launch config:
-- launch + exec (executes precompiled binary, like 'dlv exec')
-- launch + debug (builds and launches, like 'dlv debug')
-- launch + test (builds and tests, like 'dlv test')
+The server is always headless and requires a DAP client like VS Code to connect and request a binary
+to be launched or a process to be attached to. The following modes can be specified via the client's launch config:
+- launch + exec   (executes precompiled binary, like 'dlv exec')
+- launch + debug  (builds and launches, like 'dlv debug')
+- launch + test   (builds and tests, like 'dlv test')
 - launch + replay (replays an rr trace, like 'dlv replay')
-- launch + core (replays a core dump file, like 'dlv core')
-- attach + local (attaches to a running process, like 'dlv attach')
+- launch + core   (replays a core dump file, like 'dlv core')
+- attach + local  (attaches to a running process, like 'dlv attach')
+
 Program and output binary paths will be interpreted relative to dlv's working directory.
 
-The server does not yet accept multiple client connections (--accept-multiclient).
+This server does not accept multiple client connections (--accept-multiclient).
+Use 'dlv [command] --headless' instead and a DAP client with attach + remote config.
 While --continue is not supported, stopOnEntry launch/attach attribute can be used to control if
 execution is resumed at the start of the debug session.
 
@@ -38,14 +40,14 @@ dlv dap [flags]
 ### Options inherited from parent commands
 
 ```
-      --accept-multiclient               Allows a headless server to accept multiple client connections.
+      --accept-multiclient               Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
       --allow-non-terminal-interactive   Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
-      --api-version int                  Selects API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
+      --api-version int                  Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
       --backend string                   Backend selection (see 'dlv help backend'). (default "default")
       --build-flags string               Build flags, to be passed to the compiler. For example: --build-flags="-tags=integration -mod=vendor -cover -v"
       --check-go-version                 Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)
       --disable-aslr                     Disables address space randomization
-      --headless                         Run debug server only, in headless mode.
+      --headless                         Run debug server only, in headless mode. Server will accept both JSON-RPC or DAP client connections.
       --init string                      Init file, executed by the terminal client.
   -l, --listen string                    Debugging server listen address. (default "127.0.0.1:0")
       --log                              Enable debugging server logging.
diff --git a/Documentation/usage/dlv_debug.md b/Documentation/usage/dlv_debug.md
index b50413c2..718ae476 100644
--- a/Documentation/usage/dlv_debug.md
+++ b/Documentation/usage/dlv_debug.md
@@ -27,14 +27,14 @@ dlv debug [package] [flags]
 ### Options inherited from parent commands
 
 ```
-      --accept-multiclient               Allows a headless server to accept multiple client connections.
+      --accept-multiclient               Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
       --allow-non-terminal-interactive   Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
-      --api-version int                  Selects API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
+      --api-version int                  Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
       --backend string                   Backend selection (see 'dlv help backend'). (default "default")
       --build-flags string               Build flags, to be passed to the compiler. For example: --build-flags="-tags=integration -mod=vendor -cover -v"
       --check-go-version                 Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)
       --disable-aslr                     Disables address space randomization
-      --headless                         Run debug server only, in headless mode.
+      --headless                         Run debug server only, in headless mode. Server will accept both JSON-RPC or DAP client connections.
       --init string                      Init file, executed by the terminal client.
   -l, --listen string                    Debugging server listen address. (default "127.0.0.1:0")
       --log                              Enable debugging server logging.
diff --git a/Documentation/usage/dlv_exec.md b/Documentation/usage/dlv_exec.md
index 06f007e3..38e0716b 100644
--- a/Documentation/usage/dlv_exec.md
+++ b/Documentation/usage/dlv_exec.md
@@ -27,14 +27,14 @@ dlv exec <path/to/binary> [flags]
 ### Options inherited from parent commands
 
 ```
-      --accept-multiclient               Allows a headless server to accept multiple client connections.
+      --accept-multiclient               Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
       --allow-non-terminal-interactive   Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
-      --api-version int                  Selects API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
+      --api-version int                  Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
       --backend string                   Backend selection (see 'dlv help backend'). (default "default")
       --build-flags string               Build flags, to be passed to the compiler. For example: --build-flags="-tags=integration -mod=vendor -cover -v"
       --check-go-version                 Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)
       --disable-aslr                     Disables address space randomization
-      --headless                         Run debug server only, in headless mode.
+      --headless                         Run debug server only, in headless mode. Server will accept both JSON-RPC or DAP client connections.
       --init string                      Init file, executed by the terminal client.
   -l, --listen string                    Debugging server listen address. (default "127.0.0.1:0")
       --log                              Enable debugging server logging.
diff --git a/Documentation/usage/dlv_log.md b/Documentation/usage/dlv_log.md
index d925a7ea..39f92e15 100644
--- a/Documentation/usage/dlv_log.md
+++ b/Documentation/usage/dlv_log.md
@@ -38,14 +38,14 @@ and dap modes.
 ### Options inherited from parent commands
 
 ```
-      --accept-multiclient               Allows a headless server to accept multiple client connections.
+      --accept-multiclient               Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
       --allow-non-terminal-interactive   Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
-      --api-version int                  Selects API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
+      --api-version int                  Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
       --backend string                   Backend selection (see 'dlv help backend'). (default "default")
       --build-flags string               Build flags, to be passed to the compiler. For example: --build-flags="-tags=integration -mod=vendor -cover -v"
       --check-go-version                 Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)
       --disable-aslr                     Disables address space randomization
-      --headless                         Run debug server only, in headless mode.
+      --headless                         Run debug server only, in headless mode. Server will accept both JSON-RPC or DAP client connections.
       --init string                      Init file, executed by the terminal client.
   -l, --listen string                    Debugging server listen address. (default "127.0.0.1:0")
       --log                              Enable debugging server logging.
diff --git a/Documentation/usage/dlv_redirect.md b/Documentation/usage/dlv_redirect.md
index ca50e505..940b1359 100644
--- a/Documentation/usage/dlv_redirect.md
+++ b/Documentation/usage/dlv_redirect.md
@@ -26,14 +26,14 @@ File redirects can also be changed using the 'restart' command.
 ### Options inherited from parent commands
 
 ```
-      --accept-multiclient               Allows a headless server to accept multiple client connections.
+      --accept-multiclient               Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
       --allow-non-terminal-interactive   Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
-      --api-version int                  Selects API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
+      --api-version int                  Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
       --backend string                   Backend selection (see 'dlv help backend'). (default "default")
       --build-flags string               Build flags, to be passed to the compiler. For example: --build-flags="-tags=integration -mod=vendor -cover -v"
       --check-go-version                 Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)
       --disable-aslr                     Disables address space randomization
-      --headless                         Run debug server only, in headless mode.
+      --headless                         Run debug server only, in headless mode. Server will accept both JSON-RPC or DAP client connections.
       --init string                      Init file, executed by the terminal client.
   -l, --listen string                    Debugging server listen address. (default "127.0.0.1:0")
       --log                              Enable debugging server logging.
diff --git a/Documentation/usage/dlv_replay.md b/Documentation/usage/dlv_replay.md
index 89832fd0..fcc995b8 100644
--- a/Documentation/usage/dlv_replay.md
+++ b/Documentation/usage/dlv_replay.md
@@ -23,14 +23,14 @@ dlv replay [trace directory] [flags]
 ### Options inherited from parent commands
 
 ```
-      --accept-multiclient               Allows a headless server to accept multiple client connections.
+      --accept-multiclient               Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
       --allow-non-terminal-interactive   Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
-      --api-version int                  Selects API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
+      --api-version int                  Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
       --backend string                   Backend selection (see 'dlv help backend'). (default "default")
       --build-flags string               Build flags, to be passed to the compiler. For example: --build-flags="-tags=integration -mod=vendor -cover -v"
       --check-go-version                 Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)
       --disable-aslr                     Disables address space randomization
-      --headless                         Run debug server only, in headless mode.
+      --headless                         Run debug server only, in headless mode. Server will accept both JSON-RPC or DAP client connections.
       --init string                      Init file, executed by the terminal client.
   -l, --listen string                    Debugging server listen address. (default "127.0.0.1:0")
       --log                              Enable debugging server logging.
diff --git a/Documentation/usage/dlv_run.md b/Documentation/usage/dlv_run.md
index c2db3e45..6ab4b674 100644
--- a/Documentation/usage/dlv_run.md
+++ b/Documentation/usage/dlv_run.md
@@ -15,14 +15,14 @@ dlv run [flags]
 ### Options inherited from parent commands
 
 ```
-      --accept-multiclient               Allows a headless server to accept multiple client connections.
+      --accept-multiclient               Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
       --allow-non-terminal-interactive   Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
-      --api-version int                  Selects API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
+      --api-version int                  Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
       --backend string                   Backend selection (see 'dlv help backend'). (default "default")
       --build-flags string               Build flags, to be passed to the compiler. For example: --build-flags="-tags=integration -mod=vendor -cover -v"
       --check-go-version                 Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)
       --disable-aslr                     Disables address space randomization
-      --headless                         Run debug server only, in headless mode.
+      --headless                         Run debug server only, in headless mode. Server will accept both JSON-RPC or DAP client connections.
       --init string                      Init file, executed by the terminal client.
   -l, --listen string                    Debugging server listen address. (default "127.0.0.1:0")
       --log                              Enable debugging server logging.
diff --git a/Documentation/usage/dlv_trace.md b/Documentation/usage/dlv_trace.md
index fa50aa78..67a60156 100644
--- a/Documentation/usage/dlv_trace.md
+++ b/Documentation/usage/dlv_trace.md
@@ -33,14 +33,14 @@ dlv trace [package] regexp [flags]
 ### Options inherited from parent commands
 
 ```
-      --accept-multiclient               Allows a headless server to accept multiple client connections.
+      --accept-multiclient               Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
       --allow-non-terminal-interactive   Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
-      --api-version int                  Selects API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
+      --api-version int                  Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
       --backend string                   Backend selection (see 'dlv help backend'). (default "default")
       --build-flags string               Build flags, to be passed to the compiler. For example: --build-flags="-tags=integration -mod=vendor -cover -v"
       --check-go-version                 Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)
       --disable-aslr                     Disables address space randomization
-      --headless                         Run debug server only, in headless mode.
+      --headless                         Run debug server only, in headless mode. Server will accept both JSON-RPC or DAP client connections.
       --init string                      Init file, executed by the terminal client.
   -l, --listen string                    Debugging server listen address. (default "127.0.0.1:0")
       --log                              Enable debugging server logging.
diff --git a/Documentation/usage/dlv_version.md b/Documentation/usage/dlv_version.md
index 1a21d194..b1d2101c 100644
--- a/Documentation/usage/dlv_version.md
+++ b/Documentation/usage/dlv_version.md
@@ -16,14 +16,14 @@ dlv version [flags]
 ### Options inherited from parent commands
 
 ```
-      --accept-multiclient               Allows a headless server to accept multiple client connections.
+      --accept-multiclient               Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
       --allow-non-terminal-interactive   Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
-      --api-version int                  Selects API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
+      --api-version int                  Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
       --backend string                   Backend selection (see 'dlv help backend'). (default "default")
       --build-flags string               Build flags, to be passed to the compiler. For example: --build-flags="-tags=integration -mod=vendor -cover -v"
       --check-go-version                 Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)
       --disable-aslr                     Disables address space randomization
-      --headless                         Run debug server only, in headless mode.
+      --headless                         Run debug server only, in headless mode. Server will accept both JSON-RPC or DAP client connections.
       --init string                      Init file, executed by the terminal client.
   -l, --listen string                    Debugging server listen address. (default "127.0.0.1:0")
       --log                              Enable debugging server logging.
diff --git a/cmd/dlv/cmds/commands.go b/cmd/dlv/cmds/commands.go
index 15df5f63..8a0c753a 100644
--- a/cmd/dlv/cmds/commands.go
+++ b/cmd/dlv/cmds/commands.go
@@ -133,9 +133,9 @@ func New(docCall bool) *cobra.Command {
 	rootCommand.PersistentFlags().StringVarP(&logOutput, "log-output", "", "", `Comma separated list of components that should produce debug output (see 'dlv help log')`)
 	rootCommand.PersistentFlags().StringVarP(&logDest, "log-dest", "", "", "Writes logs to the specified file or file descriptor (see 'dlv help log').")
 
-	rootCommand.PersistentFlags().BoolVarP(&headless, "headless", "", false, "Run debug server only, in headless mode.")
-	rootCommand.PersistentFlags().BoolVarP(&acceptMulti, "accept-multiclient", "", false, "Allows a headless server to accept multiple client connections.")
-	rootCommand.PersistentFlags().IntVar(&apiVersion, "api-version", 1, "Selects API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md.")
+	rootCommand.PersistentFlags().BoolVarP(&headless, "headless", "", false, "Run debug server only, in headless mode. Server will accept both JSON-RPC or DAP client connections.")
+	rootCommand.PersistentFlags().BoolVarP(&acceptMulti, "accept-multiclient", "", false, "Allows a headless server to accept multiple client connections via JSON-RPC or DAP.")
+	rootCommand.PersistentFlags().IntVar(&apiVersion, "api-version", 1, "Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md.")
 	rootCommand.PersistentFlags().StringVar(&initFile, "init", "", "Init file, executed by the terminal client.")
 	rootCommand.PersistentFlags().StringVar(&buildFlags, "build-flags", buildFlagsDefault, "Build flags, to be passed to the compiler. For example: --build-flags=\"-tags=integration -mod=vendor -cover -v\"")
 	rootCommand.PersistentFlags().StringVar(&workingDir, "wd", "", "Working directory for running the program.")
@@ -170,8 +170,8 @@ option to let the process continue or kill it.
 	// 'connect' subcommand.
 	connectCommand := &cobra.Command{
 		Use:   "connect addr",
-		Short: "Connect to a headless debug server.",
-		Long:  "Connect to a running headless debug server.",
+		Short: "Connect to a headless debug server with a terminal client.",
+		Long:  "Connect to a running headless debug server with a terminal client.",
 		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
 			if len(args) == 0 {
 				return errors.New("you must provide an address as the first argument")
@@ -185,20 +185,22 @@ option to let the process continue or kill it.
 	// 'dap' subcommand.
 	dapCommand := &cobra.Command{
 		Use:   "dap",
-		Short: "[EXPERIMENTAL] Starts a headless TCP server communicating via Debug Adaptor Protocol (DAP).",
-		Long: `[EXPERIMENTAL] Starts a headless TCP server communicating via Debug Adaptor Protocol (DAP).
-
-The server is always headless and requires a DAP client like vscode to connect and request a binary
-to be launched or process to be attached to. The following modes can be specified via client's launch config:
-- launch + exec (executes precompiled binary, like 'dlv exec')
-- launch + debug (builds and launches, like 'dlv debug')
-- launch + test (builds and tests, like 'dlv test')
+		Short: "Starts a headless TCP server communicating via Debug Adaptor Protocol (DAP).",
+		Long: `Starts a headless TCP server communicating via Debug Adaptor Protocol (DAP).
+
+The server is always headless and requires a DAP client like VS Code to connect and request a binary
+to be launched or a process to be attached to. The following modes can be specified via the client's launch config:
+- launch + exec   (executes precompiled binary, like 'dlv exec')
+- launch + debug  (builds and launches, like 'dlv debug')
+- launch + test   (builds and tests, like 'dlv test')
 - launch + replay (replays an rr trace, like 'dlv replay')
-- launch + core (replays a core dump file, like 'dlv core')
-- attach + local (attaches to a running process, like 'dlv attach')
+- launch + core   (replays a core dump file, like 'dlv core')
+- attach + local  (attaches to a running process, like 'dlv attach')
+
 Program and output binary paths will be interpreted relative to dlv's working directory.
 
-The server does not yet accept multiple client connections (--accept-multiclient).
+This server does not accept multiple client connections (--accept-multiclient).
+Use 'dlv [command] --headless' instead and a DAP client with attach + remote config.
 While --continue is not supported, stopOnEntry launch/attach attribute can be used to control if
 execution is resumed at the start of the debug session.
 
diff --git a/pkg/terminal/command.go b/pkg/terminal/command.go
index 5e37271a..29f0ce74 100644
--- a/pkg/terminal/command.go
+++ b/pkg/terminal/command.go
@@ -122,16 +122,16 @@ func DebugCommands(client service.Client) *Commands {
 Type "help" followed by the name of a command for more information about it.`},
 		{aliases: []string{"break", "b"}, group: breakCmds, cmdFn: breakpoint, helpMsg: `Sets a breakpoint.
 
-	break [name] <linespec>
+	break [name] [linespec]
 
-See $GOPATH/src/github.com/go-delve/delve/Documentation/cli/locspec.md for the syntax of linespec.
+See $GOPATH/src/github.com/go-delve/delve/Documentation/cli/locspec.md for the syntax of linespec. If linespec is omitted a breakpoint will be set on the current line.
 
 See also: "help on", "help cond" and "help clear"`},
 		{aliases: []string{"trace", "t"}, group: breakCmds, cmdFn: tracepoint, allowedPrefixes: onPrefix, helpMsg: `Set tracepoint.
 
-	trace [name] <linespec>
+	trace [name] [linespec]
 
-A tracepoint is a breakpoint that does not stop the execution of the program, instead when the tracepoint is hit a notification is displayed. See $GOPATH/src/github.com/go-delve/delve/Documentation/cli/locspec.md for the syntax of linespec.
+A tracepoint is a breakpoint that does not stop the execution of the program, instead when the tracepoint is hit a notification is displayed. See $GOPATH/src/github.com/go-delve/delve/Documentation/cli/locspec.md for the syntax of linespec. If linespec is omitted a tracepoint will be set on the current line.
 
 See also: "help on", "help cond" and "help clear"`},
 		{aliases: []string{"watch"}, group: breakCmds, cmdFn: watchpoint, helpMsg: `Set watchpoint.
@@ -1681,7 +1681,12 @@ func setBreakpoint(t *Term, ctx callContext, tracepoint bool, argstr string) ([]
 	spec := ""
 	switch len(args) {
 	case 1:
-		spec = argstr
+		if len(args[0]) != 0 {
+			spec = argstr
+		} else {
+			// no arg specified
+			spec = "+0"
+		}
 	case 2:
 		if api.ValidBreakpointName(args[0]) == nil {
 			requestedBp.Name = args[0]
diff --git a/service/dap/server.go b/service/dap/server.go
index e8be53f3..44143d98 100644
--- a/service/dap/server.go
+++ b/service/dap/server.go
@@ -917,6 +917,20 @@ func (s *Session) onLaunchRequest(request *dap.LaunchRequest) {
 		}
 	}
 
+	for k, v := range args.Env {
+		if v != nil {
+			if err := os.Setenv(k, *v); err != nil {
+				s.sendShowUserErrorResponse(request.Request, FailedToLaunch, "Failed to launch", fmt.Sprintf("failed to setenv(%v) - %v", k, err))
+				return
+			}
+		} else {
+			if err := os.Unsetenv(k); err != nil {
+				s.sendShowUserErrorResponse(request.Request, FailedToLaunch, "Failed to launch", fmt.Sprintf("failed to unsetenv(%v) - %v", k, err))
+				return
+			}
+		}
+	}
+
 	if args.Mode == "" {
 		args.Mode = "debug"
 	}
@@ -1346,6 +1360,7 @@ func (s *Session) setBreakpoints(prefix string, totalBps int, metadataFunc func(
 		if _, ok := createdBps[want.name]; ok {
 			err = fmt.Errorf("breakpoint already exists")
 		} else {
+			got.Disabled = false
 			got.Cond = want.condition
 			got.HitCond = want.hitCondition
 			err = setLogMessage(got, want.logMessage)
diff --git a/service/dap/types.go b/service/dap/types.go
index 5625355a..e078b500 100644
--- a/service/dap/types.go
+++ b/service/dap/types.go
@@ -129,6 +129,15 @@ type LaunchConfig struct {
 	// directory.
 	DlvCwd string `json:"dlvCwd,omitempty"`
 
+	// Env specifies optional environment variables for Delve server
+	// in addition to the environment variables Delve initially
+	// started with.
+	// Variables with 'nil' values can be used to unset the named
+	// environment variables.
+	// Values are interpreted verbatim. Variable substitution or
+	// reference to other environment variables is not supported.
+	Env map[string]*string `json:"env,omitempty"`
+
 	LaunchAttachCommonConfig
 }
 
diff --git a/service/debugger/debugger.go b/service/debugger/debugger.go
index d5a721b1..17c562ba 100644
--- a/service/debugger/debugger.go
+++ b/service/debugger/debugger.go
@@ -770,12 +770,10 @@ func (d *Debugger) CreateEBPFTracepoint(fnName string) error {
 	return d.target.SetEBPFTracepoint(fnName)
 }
 
-// AmendBreakpoint will update the breakpoint with the matching ID.
+// amendBreakpoint will update the breakpoint with the matching ID.
 // It also enables or disables the breakpoint.
-func (d *Debugger) AmendBreakpoint(amend *api.Breakpoint) error {
-	d.targetMutex.Lock()
-	defer d.targetMutex.Unlock()
-
+// We can consume this function to avoid locking a goroutine.
+func (d *Debugger) amendBreakpoint(amend *api.Breakpoint) error {
 	originals := d.findBreakpoint(amend.ID)
 
 	if len(originals) > 0 && originals[0].WatchExpr != "" && amend.Disabled {
@@ -792,6 +790,17 @@ func (d *Debugger) AmendBreakpoint(amend *api.Breakpoint) error {
 			return err
 		}
 		copyBreakpointInfo(bp, amend)
+		if breaklet := bp.UserBreaklet(); breaklet != nil {
+			breaklet.TotalHitCount = amend.TotalHitCount
+			breaklet.HitCount = map[int]uint64{}
+			for idx := range amend.HitCount {
+				i, err := strconv.Atoi(idx)
+				if err != nil {
+					return fmt.Errorf("can't convert goroutine ID: %w", err)
+				}
+				breaklet.HitCount[i] = amend.HitCount[idx]
+			}
+		}
 		delete(d.disabledBreakpoints, amend.ID)
 	}
 	if amend.Disabled && !disabled { // disable the breakpoint
@@ -809,6 +818,15 @@ func (d *Debugger) AmendBreakpoint(amend *api.Breakpoint) error {
 	return nil
 }
 
+// AmendBreakpoint will update the breakpoint with the matching ID.
+// It also enables or disables the breakpoint.
+func (d *Debugger) AmendBreakpoint(amend *api.Breakpoint) error {
+	d.targetMutex.Lock()
+	defer d.targetMutex.Unlock()
+
+	return d.amendBreakpoint(amend)
+}
+
 // CancelNext will clear internal breakpoints, thus cancelling the 'next',
 // 'step' or 'stepout' operation.
 func (d *Debugger) CancelNext() error {
@@ -957,6 +975,33 @@ func (d *Debugger) clearBreakpoint(requestedBp *api.Breakpoint) (*api.Breakpoint
 	return clearedBp, nil
 }
 
+// isBpHitCondNotSatisfiable returns true if the breakpoint bp has a hit
+// condition that is no more satisfiable.
+// The hit condition is considered no more satisfiable if it can no longer be
+// hit again, for example with {Op: "==", Val: 1} and TotalHitCount == 1.
+func isBpHitCondNotSatisfiable(bp *api.Breakpoint) bool {
+	if bp.HitCond == "" {
+		return false
+	}
+
+	tok, val, err := parseHitCondition(bp.HitCond)
+	if err != nil {
+		return false
+	}
+	switch tok {
+	case token.EQL, token.LEQ:
+		if int(bp.TotalHitCount) >= val {
+			return true
+		}
+	case token.LSS:
+		if int(bp.TotalHitCount) >= val-1 {
+			return true
+		}
+	}
+
+	return false
+}
+
 // Breakpoints returns the list of current breakpoints.
 func (d *Debugger) Breakpoints(all bool) []*api.Breakpoint {
 	d.targetMutex.Lock()
@@ -1284,6 +1329,10 @@ func (d *Debugger) Command(command *api.DebuggerCommand, resumeNotify chan struc
 			}
 		}
 	}
+	if bp := state.CurrentThread.Breakpoint; bp != nil && isBpHitCondNotSatisfiable(bp) {
+		bp.Disabled = true
+		d.amendBreakpoint(bp)
+	}
 	return state, err
 }
 


Test patch:
diff --git a/Documentation/usage/dlv_test.md b/Documentation/usage/dlv_test.md
index 2d8526f0..9da84116 100644
--- a/Documentation/usage/dlv_test.md
+++ b/Documentation/usage/dlv_test.md
@@ -29,14 +29,14 @@ dlv test [package] [flags]
 ### Options inherited from parent commands
 
 ```
-      --accept-multiclient               Allows a headless server to accept multiple client connections.
+      --accept-multiclient               Allows a headless server to accept multiple client connections via JSON-RPC or DAP.
       --allow-non-terminal-interactive   Allows interactive sessions of Delve that don't have a terminal as stdin, stdout and stderr
-      --api-version int                  Selects API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
+      --api-version int                  Selects JSON-RPC API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
       --backend string                   Backend selection (see 'dlv help backend'). (default "default")
       --build-flags string               Build flags, to be passed to the compiler. For example: --build-flags="-tags=integration -mod=vendor -cover -v"
       --check-go-version                 Exits if the version of Go in use is not compatible (too old or too new) with the version of Delve. (default true)
       --disable-aslr                     Disables address space randomization
-      --headless                         Run debug server only, in headless mode.
+      --headless                         Run debug server only, in headless mode. Server will accept both JSON-RPC or DAP client connections.
       --init string                      Init file, executed by the terminal client.
   -l, --listen string                    Debugging server listen address. (default "127.0.0.1:0")
       --log                              Enable debugging server logging.
diff --git a/_fixtures/testenv.go b/_fixtures/testenv.go
index fdd55ea5..98cf58b8 100644
--- a/_fixtures/testenv.go
+++ b/_fixtures/testenv.go
@@ -7,7 +7,7 @@ import (
 )
 
 func main() {
-	x := os.Getenv("SOMEVAR")
+	x, y := os.LookupEnv("SOMEVAR")
 	runtime.Breakpoint()
-	fmt.Printf("SOMEVAR=%s\n", x)
+	fmt.Printf("SOMEVAR=%s\n%v", x, y)
 }
diff --git a/pkg/proc/proc_test.go b/pkg/proc/proc_test.go
index e7acf601..798aefc5 100644
--- a/pkg/proc/proc_test.go
+++ b/pkg/proc/proc_test.go
@@ -1679,7 +1679,7 @@ func TestCondBreakpoint(t *testing.T) {
 
 		n, _ := constant.Int64Val(nvar.Value)
 		if n != 7 {
-			t.Fatalf("Stoppend on wrong goroutine %d\n", n)
+			t.Fatalf("Stopped on wrong goroutine %d\n", n)
 		}
 	})
 }
@@ -1720,7 +1720,7 @@ func TestCondBreakpointError(t *testing.T) {
 
 			n, _ := constant.Int64Val(nvar.Value)
 			if n != 7 {
-				t.Fatalf("Stoppend on wrong goroutine %d\n", n)
+				t.Fatalf("Stopped on wrong goroutine %d\n", n)
 			}
 		}
 	})
@@ -1739,7 +1739,7 @@ func TestHitCondBreakpointEQ(t *testing.T) {
 
 		i, _ := constant.Int64Val(ivar.Value)
 		if i != 3 {
-			t.Fatalf("Stoppend on wrong hitcount %d\n", i)
+			t.Fatalf("Stopped on wrong hitcount %d\n", i)
 		}
 
 		err := p.Continue()
@@ -1764,7 +1764,7 @@ func TestHitCondBreakpointGEQ(t *testing.T) {
 
 			i, _ := constant.Int64Val(ivar.Value)
 			if int(i) != it {
-				t.Fatalf("Stoppend on wrong hitcount %d\n", i)
+				t.Fatalf("Stopped on wrong hitcount %d\n", i)
 			}
 		}
 
@@ -1787,7 +1787,7 @@ func TestHitCondBreakpointREM(t *testing.T) {
 
 			i, _ := constant.Int64Val(ivar.Value)
 			if int(i) != it {
-				t.Fatalf("Stoppend on wrong hitcount %d\n", i)
+				t.Fatalf("Stopped on wrong hitcount %d\n", i)
 			}
 		}
 
diff --git a/service/dap/server_test.go b/service/dap/server_test.go
index e0088dfd..4e0fc6ac 100644
--- a/service/dap/server_test.go
+++ b/service/dap/server_test.go
@@ -5509,6 +5509,106 @@ func TestLaunchRequestWithBuildFlags(t *testing.T) {
 	})
 }
 
+func TestLaunchRequestWithEnv(t *testing.T) {
+	// testenv fixture will lookup SOMEVAR with
+	//   x, y := os.Lookup("SOMEVAR")
+	// before stopping at runtime.Breakpoint.
+
+	type envMap map[string]*string
+	strVar := func(s string) *string { return &s }
+
+	fixtures := protest.FindFixturesDir() // relative to current working directory.
+	testFile, _ := filepath.Abs(filepath.Join(fixtures, "testenv.go"))
+	for _, tc := range []struct {
+		name      string
+		initEnv   envMap
+		launchEnv envMap
+		wantX     string
+		wantY     bool
+	}{
+		{
+			name:    "no env",
+			initEnv: envMap{"SOMEVAR": strVar("baz")},
+			wantX:   "baz",
+			wantY:   true,
+		},
+		{
+			name:      "overwrite",
+			initEnv:   envMap{"SOMEVAR": strVar("baz")},
+			launchEnv: envMap{"SOMEVAR": strVar("bar")},
+			wantX:     "bar",
+			wantY:     true,
+		},
+		{
+			name:      "unset",
+			initEnv:   envMap{"SOMEVAR": strVar("baz")},
+			launchEnv: envMap{"SOMEVAR": nil},
+			wantX:     "",
+			wantY:     false,
+		},
+		{
+			name:      "empty value",
+			initEnv:   envMap{"SOMEVAR": strVar("baz")},
+			launchEnv: envMap{"SOMEVAR": strVar("")},
+			wantX:     "",
+			wantY:     true,
+		},
+		{
+			name:      "set",
+			launchEnv: envMap{"SOMEVAR": strVar("foo")},
+			wantX:     "foo",
+			wantY:     true,
+		},
+		{
+			name:      "untouched",
+			initEnv:   envMap{"SOMEVAR": strVar("baz")},
+			launchEnv: envMap{"SOMEVAR2": nil, "SOMEVAR3": strVar("foo")},
+			wantX:     "baz",
+			wantY:     true,
+		},
+	} {
+
+		t.Run(tc.name, func(t *testing.T) {
+			// cleanup
+			defer func() {
+				os.Unsetenv("SOMEVAR")
+				os.Unsetenv("SOMEVAR2")
+				os.Unsetenv("SOMEVAR3")
+			}()
+
+			for k, v := range tc.initEnv {
+				if v != nil {
+					os.Setenv(k, *v)
+				}
+			}
+
+			serverStopped := make(chan struct{})
+			client := startDAPServerWithClient(t, serverStopped)
+			defer client.Close()
+
+			runDebugSessionWithBPs(t, client, "launch", func() { // launch
+				client.LaunchRequestWithArgs(map[string]interface{}{
+					"mode":    "debug",
+					"program": testFile,
+					"env":     tc.launchEnv,
+				})
+			}, testFile, nil, // runtime.Breakpoint
+				[]onBreakpoint{{
+					execute: func() {
+						client.EvaluateRequest("x", 1000, "whatever")
+						gotX := client.ExpectEvaluateResponse(t)
+						checkEval(t, gotX, fmt.Sprintf("%q", tc.wantX), false)
+						client.EvaluateRequest("y", 1000, "whatever")
+						gotY := client.ExpectEvaluateResponse(t)
+						checkEval(t, gotY, fmt.Sprintf("%v", tc.wantY), false)
+					},
+					disconnect: true,
+				}})
+			<-serverStopped
+		})
+	}
+}
+
 func TestAttachRequest(t *testing.T) {
 	if runtime.GOOS == "freebsd" {
 		t.SkipNow()
diff --git a/service/test/integration2_test.go b/service/test/integration2_test.go
index ce386910..26fc6480 100644
--- a/service/test/integration2_test.go
+++ b/service/test/integration2_test.go
@@ -615,6 +615,121 @@ func TestClientServer_toggleAmendedBreakpoint(t *testing.T) {
 	})
 }
 
+func TestClientServer_disableHitCondLSSBreakpoint(t *testing.T) {
+	withTestClient2("break", t, func(c service.Client) {
+		fp := testProgPath(t, "break")
+		hitCondBp, err := c.CreateBreakpoint(&api.Breakpoint{
+			File:    fp,
+			Line:    7,
+			HitCond: "< 3",
+		})
+		if err != nil {
+			t.Fatalf("Unexpected error: %v", err)
+		}
+
+		state := <-c.Continue()
+		if state.Err != nil {
+			t.Fatalf("Unexpected error: %v, state: %#v", state.Err, state)
+		}
+
+		f, l := state.CurrentThread.File, state.CurrentThread.Line
+		if f != "break.go" && l != 7 {
+			t.Fatal("Program did not hit breakpoint")
+		}
+
+		ivar, err := c.EvalVariable(api.EvalScope{GoroutineID: -1}, "i", normalLoadConfig)
+		assertNoError(err, t, "EvalVariable")
+
+		t.Logf("ivar: %s", ivar.SinglelineString())
+
+		if ivar.Value != "1" {
+			t.Fatalf("Wrong variable value: %s", ivar.Value)
+		}
+
+		bp, err := c.GetBreakpoint(hitCondBp.ID)
+		assertNoError(err, t, "GetBreakpoint()")
+
+		if bp.Disabled {
+			t.Fatalf(
+				"Hit condition %s is still satisfiable but breakpoint has been disabled",
+				bp.HitCond,
+			)
+		}
+
+		state = <-c.Continue()
+		if state.Err != nil {
+			t.Fatalf("Unexpected error: %v, state: %#v", state.Err, state)
+		}
+
+		f, l = state.CurrentThread.File, state.CurrentThread.Line
+		if f != "break.go" && l != 7 {
+			t.Fatal("Program did not hit breakpoint")
+		}
+
+		ivar, err = c.EvalVariable(api.EvalScope{GoroutineID: -1}, "i", normalLoadConfig)
+		assertNoError(err, t, "EvalVariable")
+
+		t.Logf("ivar: %s", ivar.SinglelineString())
+
+		if ivar.Value != "2" {
+			t.Fatalf("Wrong variable value: %s", ivar.Value)
+		}
+
+		bp, err = c.GetBreakpoint(hitCondBp.ID)
+		assertNoError(err, t, "GetBreakpoint()")
+
+		if !bp.Disabled {
+			t.Fatalf(
+				"Hit condition %s is no more satisfiable but breakpoint has not been disabled",
+				bp.HitCond,
+			)
+		}
+	})
+}
+
+func TestClientServer_disableHitEQLCondBreakpoint(t *testing.T) {
+	withTestClient2("break", t, func(c service.Client) {
+		fp := testProgPath(t, "break")
+		hitCondBp, err := c.CreateBreakpoint(&api.Breakpoint{
+			File:    fp,
+			Line:    7,
+			HitCond: "== 3",
+		})
+		if err != nil {
+			t.Fatalf("Unexpected error: %v", err)
+		}
+
+		state := <-c.Continue()
+		if state.Err != nil {
+			t.Fatalf("Unexpected error: %v, state: %#v", state.Err, state)
+		}
+
+		f, l := state.CurrentThread.File, state.CurrentThread.Line
+		if f != "break.go" && l != 7 {
+			t.Fatal("Program did not hit breakpoint")
+		}
+
+		ivar, err := c.EvalVariable(api.EvalScope{GoroutineID: -1}, "i", normalLoadConfig)
+		assertNoError(err, t, "EvalVariable")
+
+		t.Logf("ivar: %s", ivar.SinglelineString())
+
+		if ivar.Value != "3" {
+			t.Fatalf("Wrong variable value: %s", ivar.Value)
+		}
+
+		bp, err := c.GetBreakpoint(hitCondBp.ID)
+		assertNoError(err, t, "GetBreakpoint()")
+
+		if !bp.Disabled {
+			t.Fatalf(
+				"Hit condition %s is no more satisfiable but breakpoint has not been disabled",
+				bp.HitCond,
+			)
+		}
+	})
+}
+
 func TestClientServer_switchThread(t *testing.T) {
 	protest.AllowRecording(t)
 	withTestClient2("testnextprog", t, func(c service.Client) {