gopls/internal/protocol/command: use gopls.foo form everywhere

Before, the command.Command enum values (e.g. "run_tests") did
not match the actual command strings used in the Command field
of protocol.Command (e.g. "gopls.run_tests").

This change causes us to use the "gopls."-prefixed form everywhere,
avoiding the need for various conversions, and the opportunity
to forget to make them.

Also
- tidy up the commands.md markdown.
- remove 2x TODOs about eliminating Command.Title:
  I think it works nicely in the documentation.
- remove ⬤ blobs from markdown by popular demand.

Change-Id: Ida5981ba834ea148fa0267319cf874b9a48c9289
Reviewed-on: https://go-review.googlesource.com/c/tools/+/591175
Auto-Submit: Alan Donovan <adonovan@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Findley <rfindley@google.com>
diff --git a/gopls/doc/codelenses.md b/gopls/doc/codelenses.md
index 378a3db..3477627 100644
--- a/gopls/doc/codelenses.md
+++ b/gopls/doc/codelenses.md
@@ -16,7 +16,7 @@
 
 <!-- This portion is generated by doc/generate from the ../internal/settings package. -->
 <!-- BEGIN Lenses: DO NOT MANUALLY EDIT THIS SECTION -->
-## ⬤ `gc_details`: Toggle display of Go compiler optimization decisions
+## `gc_details`: Toggle display of Go compiler optimization decisions
 
 
 This codelens source causes the `package` declaration of
@@ -40,7 +40,7 @@
 
 File type: Go
 
-## ⬤ `generate`: Run `go generate`
+## `generate`: Run `go generate`
 
 
 This codelens source annotates any `//go:generate` comments
@@ -55,7 +55,7 @@
 
 File type: Go
 
-## ⬤ `regenerate_cgo`: Re-generate cgo declarations
+## `regenerate_cgo`: Re-generate cgo declarations
 
 
 This codelens source annotates an `import "C"` declaration
@@ -71,7 +71,7 @@
 
 File type: Go
 
-## ⬤ `test`: Run tests and benchmarks
+## `test`: Run tests and benchmarks
 
 
 This codelens source annotates each `Test` and `Benchmark`
@@ -90,7 +90,7 @@
 
 File type: Go
 
-## ⬤ `run_govulncheck`: Run govulncheck
+## `run_govulncheck`: Run govulncheck
 
 
 This codelens source annotates the `module` directive in a
@@ -107,7 +107,7 @@
 
 File type: go.mod
 
-## ⬤ `tidy`: Tidy go.mod file
+## `tidy`: Tidy go.mod file
 
 
 This codelens source annotates the `module` directive in a
@@ -120,7 +120,7 @@
 
 File type: go.mod
 
-## ⬤ `upgrade_dependency`: Update dependencies
+## `upgrade_dependency`: Update dependencies
 
 
 This codelens source annotates the `module` directive in a
@@ -135,7 +135,7 @@
 
 File type: go.mod
 
-## ⬤ `vendor`: Update vendor directory
+## `vendor`: Update vendor directory
 
 
 This codelens source annotates the `module` directive in a
diff --git a/gopls/doc/commands.md b/gopls/doc/commands.md
index 1e15310..69c3af8 100644
--- a/gopls/doc/commands.md
+++ b/gopls/doc/commands.md
@@ -3,8 +3,7 @@
 This document describes the LSP-level commands supported by `gopls`. They cannot be invoked directly by users, and all the details are subject to change, so nobody should rely on this information.
 
 <!-- BEGIN Commands: DO NOT MANUALLY EDIT THIS SECTION -->
-### **Add a dependency**
-Identifier: `gopls.add_dependency`
+## `gopls.add_dependency`: **Add a dependency**
 
 Adds a dependency to the go.mod file for a module.
 
@@ -21,8 +20,7 @@
 }
 ```
 
-### **Add an import**
-Identifier: `gopls.add_import`
+## `gopls.add_import`: **Add an import**
 
 Ask the server to add an import path to a given Go file.  The method will
 call applyEdit on the client so that clients don't have to apply the edit
@@ -41,8 +39,7 @@
 }
 ```
 
-### **Update the given telemetry counters**
-Identifier: `gopls.add_telemetry_counters`
+## `gopls.add_telemetry_counters`: **Update the given telemetry counters**
 
 Gopls will prepend "fwd/" to all the counters updated using this command
 to avoid conflicts with other counters gopls collects.
@@ -57,8 +54,7 @@
 }
 ```
 
-### **Apply a fix**
-Identifier: `gopls.apply_fix`
+## `gopls.apply_fix`: **Apply a fix**
 
 Applies a fix to a region of source code.
 
@@ -144,8 +140,7 @@
 }
 ```
 
-### **Perform a "change signature" refactoring**
-Identifier: `gopls.change_signature`
+## `gopls.change_signature`: **Perform a "change signature" refactoring**
 
 This command is experimental, currently only supporting parameter removal.
 Its signature will certainly change in the future (pun intended).
@@ -217,8 +212,7 @@
 }
 ```
 
-### **Check for upgrades**
-Identifier: `gopls.check_upgrades`
+## `gopls.check_upgrades`: **Check for upgrades**
 
 Checks for module upgrades.
 
@@ -233,8 +227,7 @@
 }
 ```
 
-### **Cause server to publish diagnostics for the specified files.**
-Identifier: `gopls.diagnose_files`
+## `gopls.diagnose_files`: **Cause server to publish diagnostics for the specified files.**
 
 This command is needed by the 'gopls {check,fix}' CLI subcommands.
 
@@ -246,8 +239,7 @@
 }
 ```
 
-### **View package documentation.**
-Identifier: `gopls.doc`
+## `gopls.doc`: **View package documentation.**
 
 Opens the Go package documentation page for the current
 package in a browser.
@@ -270,8 +262,7 @@
 }
 ```
 
-### **Run go mod edit -go=version**
-Identifier: `gopls.edit_go_directive`
+## `gopls.edit_go_directive`: **Run go mod edit -go=version**
 
 Runs `go mod edit -go=version` for a module.
 
@@ -286,8 +277,7 @@
 }
 ```
 
-### **Get known vulncheck result**
-Identifier: `gopls.fetch_vulncheck_result`
+## `gopls.fetch_vulncheck_result`: **Get known vulncheck result**
 
 Fetch the result of latest vulnerability check (`govulncheck`).
 
@@ -306,8 +296,7 @@
 map[golang.org/x/tools/gopls/internal/protocol.DocumentURI]*golang.org/x/tools/gopls/internal/vulncheck.Result
 ```
 
-### **report free symbols referenced by the selection.**
-Identifier: `gopls.free_symbols`
+## `gopls.free_symbols`: **report free symbols referenced by the selection.**
 
 This command is a query over a selected range of Go source
 code. It reports the set of "free" symbols of the
@@ -335,8 +324,7 @@
 }
 ```
 
-### **Toggle gc_details**
-Identifier: `gopls.gc_details`
+## `gopls.gc_details`: **Toggle gc_details**
 
 Toggle the calculation of gc annotations.
 
@@ -346,8 +334,7 @@
 string
 ```
 
-### **Run go generate**
-Identifier: `gopls.generate`
+## `gopls.generate`: **Run go generate**
 
 Runs `go generate` for a given directory.
 
@@ -362,8 +349,7 @@
 }
 ```
 
-### **'go get' a package**
-Identifier: `gopls.go_get_package`
+## `gopls.go_get_package`: **'go get' a package**
 
 Runs `go get` to fetch a package.
 
@@ -379,8 +365,7 @@
 }
 ```
 
-### **List imports of a file and its package**
-Identifier: `gopls.list_imports`
+## `gopls.list_imports`: **List imports of a file and its package**
 
 Retrieve a list of imports in the given Go file, and the package it
 belongs to.
@@ -410,8 +395,7 @@
 }
 ```
 
-### **List known packages**
-Identifier: `gopls.list_known_packages`
+## `gopls.list_known_packages`: **List known packages**
 
 Retrieve a list of packages that are importable from the given URI.
 
@@ -437,15 +421,13 @@
 }
 ```
 
-### **Prompt user to enable telemetry**
-Identifier: `gopls.maybe_prompt_for_telemetry`
+## `gopls.maybe_prompt_for_telemetry`: **Prompt user to enable telemetry**
 
 Checks for the right conditions, and then prompts the user
 to ask if they want to enable Go telemetry uploading. If
 the user responds 'Yes', the telemetry mode is set to "on".
 
-### **Fetch memory statistics**
-Identifier: `gopls.mem_stats`
+## `gopls.mem_stats`: **Fetch memory statistics**
 
 Call runtime.GC multiple times and return memory statistics as reported by
 runtime.MemStats.
@@ -462,8 +444,7 @@
 }
 ```
 
-### **Regenerate cgo**
-Identifier: `gopls.regenerate_cgo`
+## `gopls.regenerate_cgo`: **Regenerate cgo**
 
 Regenerates cgo definitions.
 
@@ -476,8 +457,7 @@
 }
 ```
 
-### **Remove a dependency**
-Identifier: `gopls.remove_dependency`
+## `gopls.remove_dependency`: **Remove a dependency**
 
 Removes a dependency from the go.mod file of a module.
 
@@ -496,8 +476,7 @@
 }
 ```
 
-### **Reset go.mod diagnostics**
-Identifier: `gopls.reset_go_mod_diagnostics`
+## `gopls.reset_go_mod_diagnostics`: **Reset go.mod diagnostics**
 
 Reset diagnostics in the go.mod file of a module.
 
@@ -514,8 +493,7 @@
 }
 ```
 
-### **Run `go work [args...]`, and apply the resulting go.work**
-Identifier: `gopls.run_go_work_command`
+## `gopls.run_go_work_command`: **Run `go work [args...]`, and apply the resulting go.work**
 
 edits to the current go.work file
 
@@ -529,8 +507,7 @@
 }
 ```
 
-### **Run vulncheck**
-Identifier: `gopls.run_govulncheck`
+## `gopls.run_govulncheck`: **Run vulncheck**
 
 Run vulnerability check (`govulncheck`).
 
@@ -557,8 +534,7 @@
 }
 ```
 
-### **Run test(s)**
-Identifier: `gopls.run_tests`
+## `gopls.run_tests`: **Run test(s)**
 
 Runs `go test` for a specific set of test or benchmark functions.
 
@@ -577,8 +553,7 @@
 }
 ```
 
-### **Start the gopls debug server**
-Identifier: `gopls.start_debugging`
+## `gopls.start_debugging`: **Start the gopls debug server**
 
 Start the gopls debug server if it isn't running, and return the debug
 address.
@@ -622,8 +597,7 @@
 }
 ```
 
-### **Start capturing a profile of gopls' execution**
-Identifier: `gopls.start_profile`
+## `gopls.start_profile`: **Start capturing a profile of gopls' execution**
 
 Start a new pprof profile. Before using the resulting file, profiling must
 be stopped with a corresponding call to StopProfile.
@@ -643,8 +617,7 @@
 struct{}
 ```
 
-### **Stop an ongoing profile**
-Identifier: `gopls.stop_profile`
+## `gopls.stop_profile`: **Stop an ongoing profile**
 
 This command is intended for internal use only, by the gopls benchmark
 runner.
@@ -664,8 +637,7 @@
 }
 ```
 
-### **Run test(s) (legacy)**
-Identifier: `gopls.test`
+## `gopls.test`: **Run test(s) (legacy)**
 
 Runs `go test` for a specific set of test or benchmark functions.
 
@@ -684,8 +656,7 @@
 []string
 ```
 
-### **Run go mod tidy**
-Identifier: `gopls.tidy`
+## `gopls.tidy`: **Run go mod tidy**
 
 Runs `go mod tidy` for a module.
 
@@ -698,8 +669,7 @@
 }
 ```
 
-### **Toggle gc_details**
-Identifier: `gopls.toggle_gc_details`
+## `gopls.toggle_gc_details`: **Toggle gc_details**
 
 Toggle the calculation of gc annotations.
 
@@ -712,8 +682,7 @@
 }
 ```
 
-### **Update go.sum**
-Identifier: `gopls.update_go_sum`
+## `gopls.update_go_sum`: **Update go.sum**
 
 Updates the go.sum file for a module.
 
@@ -726,8 +695,7 @@
 }
 ```
 
-### **Upgrade a dependency**
-Identifier: `gopls.upgrade_dependency`
+## `gopls.upgrade_dependency`: **Upgrade a dependency**
 
 Upgrades a dependency in the go.mod file for a module.
 
@@ -744,8 +712,7 @@
 }
 ```
 
-### **Run go mod vendor**
-Identifier: `gopls.vendor`
+## `gopls.vendor`: **Run go mod vendor**
 
 Runs `go mod vendor` for a module.
 
@@ -758,8 +725,7 @@
 }
 ```
 
-### **List current Views on the server.**
-Identifier: `gopls.views`
+## `gopls.views`: **List current Views on the server.**
 
 This command is intended for use by gopls tests only.
 
@@ -775,8 +741,7 @@
 }
 ```
 
-### **Fetch workspace statistics**
-Identifier: `gopls.workspace_stats`
+## `gopls.workspace_stats`: **Fetch workspace statistics**
 
 Query statistics about workspace builds, modules, packages, and files.
 
diff --git a/gopls/doc/generate/generate.go b/gopls/doc/generate/generate.go
index f49a787..3373527 100644
--- a/gopls/doc/generate/generate.go
+++ b/gopls/doc/generate/generate.go
@@ -40,7 +40,6 @@
 	"golang.org/x/tools/gopls/internal/golang"
 	"golang.org/x/tools/gopls/internal/mod"
 	"golang.org/x/tools/gopls/internal/protocol"
-	"golang.org/x/tools/gopls/internal/protocol/command"
 	"golang.org/x/tools/gopls/internal/protocol/command/commandmeta"
 	"golang.org/x/tools/gopls/internal/settings"
 	"golang.org/x/tools/gopls/internal/util/maps"
@@ -170,10 +169,6 @@
 		return nil, err
 	}
 
-	// Transform the internal command name to the external command name.
-	for _, c := range api.Commands {
-		c.Command = command.ID(c.Command)
-	}
 	api.Hints = loadHints(golang.AllInlayHints)
 	for _, category := range []reflect.Value{
 		reflect.ValueOf(defaults.UserOptions),
@@ -707,8 +702,6 @@
 				fmt.Fprintf(&buf, "<a id='%s'></a>\n", opt.Name)
 
 				// heading
-				// (The blob helps the reader see the start of each item,
-				// which is otherwise hard to discern in GitHub markdown.)
 				//
 				// TODO(adonovan): We should display not the Go type (e.g.
 				// `time.Duration`, `map[Enum]bool`) for each setting,
@@ -720,7 +713,7 @@
 				//
 				// We do not display the undocumented dotted-path alias
 				// (h.title + "." + opt.Name) used by VS Code only.
-				fmt.Fprintf(&buf, "### ⬤ `%s` *%v*\n\n", opt.Name, opt.Type)
+				fmt.Fprintf(&buf, "### `%s` *%v*\n\n", opt.Name, opt.Type)
 
 				// status
 				switch opt.Status {
@@ -848,7 +841,7 @@
 func rewriteCodeLenses(prevContent []byte, api *doc.API) ([]byte, error) {
 	var buf bytes.Buffer
 	for _, lens := range api.Lenses {
-		fmt.Fprintf(&buf, "## ⬤ `%s`: %s\n\n", lens.Lens, lens.Title)
+		fmt.Fprintf(&buf, "## `%s`: %s\n\n", lens.Lens, lens.Title)
 		fmt.Fprintf(&buf, "%s\n\n", lens.Doc)
 		fmt.Fprintf(&buf, "Default: %v\n\n", onOff(lens.Default))
 		fmt.Fprintf(&buf, "File type: %s\n\n", lens.FileType)
@@ -859,7 +852,7 @@
 func rewriteCommands(prevContent []byte, api *doc.API) ([]byte, error) {
 	var buf bytes.Buffer
 	for _, command := range api.Commands {
-		fmt.Fprintf(&buf, "### **%v**\nIdentifier: `%v`\n\n%v\n\n", command.Title, command.Command, command.Doc)
+		fmt.Fprintf(&buf, "## `%s`: **%s**\n\n%v\n\n", command.Command, command.Title, command.Doc)
 		if command.ArgDoc != "" {
 			fmt.Fprintf(&buf, "Args:\n\n```\n%s\n```\n\n", command.ArgDoc)
 		}
diff --git a/gopls/doc/settings.md b/gopls/doc/settings.md
index a3c5bb5..83f6280 100644
--- a/gopls/doc/settings.md
+++ b/gopls/doc/settings.md
@@ -48,7 +48,7 @@
 ## Build
 
 <a id='buildFlags'></a>
-### ⬤ `buildFlags` *[]string*
+### `buildFlags` *[]string*
 
 buildFlags is the set of flags passed on to the build system when invoked.
 It is applied to queries like `go list`, which is used when discovering files.
@@ -57,14 +57,14 @@
 Default: `[]`.
 
 <a id='env'></a>
-### ⬤ `env` *map[string]string*
+### `env` *map[string]string*
 
 env adds environment variables to external commands run by `gopls`, most notably `go list`.
 
 Default: `{}`.
 
 <a id='directoryFilters'></a>
-### ⬤ `directoryFilters` *[]string*
+### `directoryFilters` *[]string*
 
 directoryFilters can be used to exclude unwanted directories from the
 workspace. By default, all directories are included. Filters are an
@@ -88,7 +88,7 @@
 Default: `["-**/node_modules"]`.
 
 <a id='templateExtensions'></a>
-### ⬤ `templateExtensions` *[]string*
+### `templateExtensions` *[]string*
 
 templateExtensions gives the extensions of file names that are treateed
 as template files. (The extension
@@ -97,7 +97,7 @@
 Default: `[]`.
 
 <a id='memoryMode'></a>
-### ⬤ `memoryMode` *string*
+### `memoryMode` *string*
 
 **This setting is experimental and may be deleted.**
 
@@ -106,7 +106,7 @@
 Default: `""`.
 
 <a id='expandWorkspaceToModule'></a>
-### ⬤ `expandWorkspaceToModule` *bool*
+### `expandWorkspaceToModule` *bool*
 
 **This setting is experimental and may be deleted.**
 
@@ -122,7 +122,7 @@
 Default: `true`.
 
 <a id='allowImplicitNetworkAccess'></a>
-### ⬤ `allowImplicitNetworkAccess` *bool*
+### `allowImplicitNetworkAccess` *bool*
 
 **This setting is experimental and may be deleted.**
 
@@ -133,7 +133,7 @@
 Default: `false`.
 
 <a id='standaloneTags'></a>
-### ⬤ `standaloneTags` *[]string*
+### `standaloneTags` *[]string*
 
 standaloneTags specifies a set of build constraints that identify
 individual Go source files that make up the entire main package of an
@@ -160,7 +160,7 @@
 ## Formatting
 
 <a id='local'></a>
-### ⬤ `local` *string*
+### `local` *string*
 
 local is the equivalent of the `goimports -local` flag, which puts
 imports beginning with this string after third-party packages. It should
@@ -170,7 +170,7 @@
 Default: `""`.
 
 <a id='gofumpt'></a>
-### ⬤ `gofumpt` *bool*
+### `gofumpt` *bool*
 
 gofumpt indicates if we should run gofumpt formatting.
 
@@ -180,7 +180,7 @@
 ## UI
 
 <a id='codelenses'></a>
-### ⬤ `codelenses` *map[golang.org/x/tools/gopls/internal/protocol.CodeLensSource]bool*
+### `codelenses` *map[golang.org/x/tools/gopls/internal/protocol.CodeLensSource]bool*
 
 codelenses overrides the enabled/disabled state of each of gopls'
 sources of [Code Lenses](codelenses.md).
@@ -201,7 +201,7 @@
 Default: `{"gc_details":false,"generate":true,"regenerate_cgo":true,"run_govulncheck":false,"tidy":true,"upgrade_dependency":true,"vendor":true}`.
 
 <a id='semanticTokens'></a>
-### ⬤ `semanticTokens` *bool*
+### `semanticTokens` *bool*
 
 **This setting is experimental and may be deleted.**
 
@@ -211,7 +211,7 @@
 Default: `false`.
 
 <a id='noSemanticString'></a>
-### ⬤ `noSemanticString` *bool*
+### `noSemanticString` *bool*
 
 **This setting is experimental and may be deleted.**
 
@@ -220,7 +220,7 @@
 Default: `false`.
 
 <a id='noSemanticNumber'></a>
-### ⬤ `noSemanticNumber` *bool*
+### `noSemanticNumber` *bool*
 
 **This setting is experimental and may be deleted.**
 
@@ -232,7 +232,7 @@
 ## Completion
 
 <a id='usePlaceholders'></a>
-### ⬤ `usePlaceholders` *bool*
+### `usePlaceholders` *bool*
 
 placeholders enables placeholders for function parameters or struct
 fields in completion responses.
@@ -240,7 +240,7 @@
 Default: `false`.
 
 <a id='completionBudget'></a>
-### ⬤ `completionBudget` *time.Duration*
+### `completionBudget` *time.Duration*
 
 **This setting is for debugging purposes only.**
 
@@ -253,7 +253,7 @@
 Default: `"100ms"`.
 
 <a id='matcher'></a>
-### ⬤ `matcher` *enum*
+### `matcher` *enum*
 
 **This is an advanced setting and should not be configured by most `gopls` users.**
 
@@ -269,7 +269,7 @@
 Default: `"Fuzzy"`.
 
 <a id='experimentalPostfixCompletions'></a>
-### ⬤ `experimentalPostfixCompletions` *bool*
+### `experimentalPostfixCompletions` *bool*
 
 **This setting is experimental and may be deleted.**
 
@@ -279,7 +279,7 @@
 Default: `true`.
 
 <a id='completeFunctionCalls'></a>
-### ⬤ `completeFunctionCalls` *bool*
+### `completeFunctionCalls` *bool*
 
 completeFunctionCalls enables function call completion.
 
@@ -293,7 +293,7 @@
 ## Diagnostic
 
 <a id='analyses'></a>
-### ⬤ `analyses` *map[string]bool*
+### `analyses` *map[string]bool*
 
 analyses specify analyses that the user would like to enable or disable.
 A map of the names of analysis passes that should be enabled/disabled.
@@ -314,7 +314,7 @@
 Default: `{}`.
 
 <a id='staticcheck'></a>
-### ⬤ `staticcheck` *bool*
+### `staticcheck` *bool*
 
 **This setting is experimental and may be deleted.**
 
@@ -325,7 +325,7 @@
 Default: `false`.
 
 <a id='annotations'></a>
-### ⬤ `annotations` *map[string]bool*
+### `annotations` *map[string]bool*
 
 **This setting is experimental and may be deleted.**
 
@@ -342,7 +342,7 @@
 Default: `{"bounds":true,"escape":true,"inline":true,"nil":true}`.
 
 <a id='vulncheck'></a>
-### ⬤ `vulncheck` *enum*
+### `vulncheck` *enum*
 
 **This setting is experimental and may be deleted.**
 
@@ -357,7 +357,7 @@
 Default: `"Off"`.
 
 <a id='diagnosticsDelay'></a>
-### ⬤ `diagnosticsDelay` *time.Duration*
+### `diagnosticsDelay` *time.Duration*
 
 **This is an advanced setting and should not be configured by most `gopls` users.**
 
@@ -371,7 +371,7 @@
 Default: `"1s"`.
 
 <a id='diagnosticsTrigger'></a>
-### ⬤ `diagnosticsTrigger` *enum*
+### `diagnosticsTrigger` *enum*
 
 **This setting is experimental and may be deleted.**
 
@@ -386,7 +386,7 @@
 Default: `"Edit"`.
 
 <a id='analysisProgressReporting'></a>
-### ⬤ `analysisProgressReporting` *bool*
+### `analysisProgressReporting` *bool*
 
 analysisProgressReporting controls whether gopls sends progress
 notifications when construction of its index of analysis facts is taking a
@@ -404,7 +404,7 @@
 ## Documentation
 
 <a id='hoverKind'></a>
-### ⬤ `hoverKind` *enum*
+### `hoverKind` *enum*
 
 hoverKind controls the information that appears in the hover text.
 SingleLine and Structured are intended for use only by authors of editor plugins.
@@ -423,7 +423,7 @@
 Default: `"FullDocumentation"`.
 
 <a id='linkTarget'></a>
-### ⬤ `linkTarget` *string*
+### `linkTarget` *string*
 
 linkTarget controls where documentation links go.
 It might be one of:
@@ -439,7 +439,7 @@
 Default: `"pkg.go.dev"`.
 
 <a id='linksInHover'></a>
-### ⬤ `linksInHover` *bool*
+### `linksInHover` *bool*
 
 linksInHover toggles the presence of links to documentation in hover.
 
@@ -449,7 +449,7 @@
 ## Inlayhint
 
 <a id='hints'></a>
-### ⬤ `hints` *map[string]bool*
+### `hints` *map[string]bool*
 
 **This setting is experimental and may be deleted.**
 
@@ -463,7 +463,7 @@
 ## Navigation
 
 <a id='importShortcut'></a>
-### ⬤ `importShortcut` *enum*
+### `importShortcut` *enum*
 
 importShortcut specifies whether import statements should link to
 documentation or go to definitions.
@@ -477,7 +477,7 @@
 Default: `"Both"`.
 
 <a id='symbolMatcher'></a>
-### ⬤ `symbolMatcher` *enum*
+### `symbolMatcher` *enum*
 
 **This is an advanced setting and should not be configured by most `gopls` users.**
 
@@ -493,7 +493,7 @@
 Default: `"FastFuzzy"`.
 
 <a id='symbolStyle'></a>
-### ⬤ `symbolStyle` *enum*
+### `symbolStyle` *enum*
 
 **This is an advanced setting and should not be configured by most `gopls` users.**
 
@@ -523,7 +523,7 @@
 Default: `"Dynamic"`.
 
 <a id='symbolScope'></a>
-### ⬤ `symbolScope` *enum*
+### `symbolScope` *enum*
 
 symbolScope controls which packages are searched for workspace/symbol
 requests. When the scope is "workspace", gopls searches only workspace
@@ -539,7 +539,7 @@
 Default: `"all"`.
 
 <a id='verboseOutput'></a>
-### ⬤ `verboseOutput` *bool*
+### `verboseOutput` *bool*
 
 **This setting is for debugging purposes only.**
 
diff --git a/gopls/internal/cmd/execute.go b/gopls/internal/cmd/execute.go
index 485e6d0..0797c9f 100644
--- a/gopls/internal/cmd/execute.go
+++ b/gopls/internal/cmd/execute.go
@@ -11,7 +11,6 @@
 	"fmt"
 	"log"
 	"os"
-	"strings"
 
 	"golang.org/x/tools/gopls/internal/protocol"
 	"golang.org/x/tools/gopls/internal/protocol/command"
@@ -58,7 +57,7 @@
 		return tool.CommandLineErrorf("execute requires a command name")
 	}
 	cmd := args[0]
-	if !slices.Contains(command.Commands, command.Command(strings.TrimPrefix(cmd, "gopls."))) {
+	if !slices.Contains(command.Commands, command.Command(cmd)) {
 		return tool.CommandLineErrorf("unrecognized command: %s", cmd)
 	}
 
@@ -127,8 +126,7 @@
 
 	// Some commands are asynchronous, so clients
 	// must wait for the "end" progress notification.
-	enum := command.Command(strings.TrimPrefix(cmd.Command, "gopls."))
-	if enum.IsAsync() {
+	if command.Command(cmd.Command).IsAsync() {
 		status := <-endStatus
 		if status != server.CommandCompleted {
 			return nil, fmt.Errorf("command %s", status)
diff --git a/gopls/internal/cmd/remote.go b/gopls/internal/cmd/remote.go
index 8de4365..ae4aa55 100644
--- a/gopls/internal/cmd/remote.go
+++ b/gopls/internal/cmd/remote.go
@@ -151,7 +151,7 @@
 		Addr: debugAddr,
 	}
 	var result command.DebuggingResult
-	if err := lsprpc.ExecuteCommand(ctx, remote, command.StartDebugging.ID(), debugArgs, &result); err != nil {
+	if err := lsprpc.ExecuteCommand(ctx, remote, command.StartDebugging.String(), debugArgs, &result); err != nil {
 		return err
 	}
 	if len(result.URLs) == 0 {
diff --git a/gopls/internal/cmd/stats.go b/gopls/internal/cmd/stats.go
index a788801..cc19a94 100644
--- a/gopls/internal/cmd/stats.go
+++ b/gopls/internal/cmd/stats.go
@@ -128,7 +128,7 @@
 
 	if _, err := do("Querying memstats", func() error {
 		memStats, err := conn.executeCommand(ctx, &protocol.Command{
-			Command: command.MemStats.ID(),
+			Command: command.MemStats.String(),
 		})
 		if err != nil {
 			return err
@@ -141,7 +141,7 @@
 
 	if _, err := do("Querying workspace stats", func() error {
 		wsStats, err := conn.executeCommand(ctx, &protocol.Command{
-			Command: command.WorkspaceStats.ID(),
+			Command: command.WorkspaceStats.String(),
 		})
 		if err != nil {
 			return err
diff --git a/gopls/internal/doc/api.go b/gopls/internal/doc/api.go
index 54bd917..62e6b5b 100644
--- a/gopls/internal/doc/api.go
+++ b/gopls/internal/doc/api.go
@@ -55,7 +55,7 @@
 }
 
 type Command struct {
-	Command   string
+	Command   string // e.g. "gopls.run_tests"
 	Title     string
 	Doc       string
 	ArgDoc    string
diff --git a/gopls/internal/lsprpc/lsprpc.go b/gopls/internal/lsprpc/lsprpc.go
index ceb47aa..b77557c 100644
--- a/gopls/internal/lsprpc/lsprpc.go
+++ b/gopls/internal/lsprpc/lsprpc.go
@@ -290,7 +290,7 @@
 		case "workspace/executeCommand":
 			var params protocol.ExecuteCommandParams
 			if err := json.Unmarshal(r.Params(), &params); err == nil {
-				if params.Command == command.StartDebugging.ID() {
+				if params.Command == command.StartDebugging.String() {
 					var args command.DebuggingArgs
 					if err := command.UnmarshalArgs(params.Arguments, &args); err == nil {
 						reply = f.replyWithDebugAddress(ctx, reply, args)
diff --git a/gopls/internal/protocol/command/command_gen.go b/gopls/internal/protocol/command/command_gen.go
index fe4b7d3..5e267af 100644
--- a/gopls/internal/protocol/command/command_gen.go
+++ b/gopls/internal/protocol/command/command_gen.go
@@ -18,45 +18,47 @@
 	"golang.org/x/tools/gopls/internal/protocol"
 )
 
-// Symbolic names for gopls commands, excluding "gopls." prefix.
-// These commands may be requested by ExecuteCommand, CodeLens,
-// CodeAction, and other LSP requests.
+// Symbolic names for gopls commands, corresponding to methods of [Interface].
+//
+// The string value is used in the Command field of protocol.Command.
+// These commands may be obtained from a CodeLens or CodeAction request
+// and executed by an ExecuteCommand request.
 const (
-	AddDependency           Command = "add_dependency"
-	AddImport               Command = "add_import"
-	AddTelemetryCounters    Command = "add_telemetry_counters"
-	ApplyFix                Command = "apply_fix"
-	ChangeSignature         Command = "change_signature"
-	CheckUpgrades           Command = "check_upgrades"
-	DiagnoseFiles           Command = "diagnose_files"
-	Doc                     Command = "doc"
-	EditGoDirective         Command = "edit_go_directive"
-	FetchVulncheckResult    Command = "fetch_vulncheck_result"
-	FreeSymbols             Command = "free_symbols"
-	GCDetails               Command = "gc_details"
-	Generate                Command = "generate"
-	GoGetPackage            Command = "go_get_package"
-	ListImports             Command = "list_imports"
-	ListKnownPackages       Command = "list_known_packages"
-	MaybePromptForTelemetry Command = "maybe_prompt_for_telemetry"
-	MemStats                Command = "mem_stats"
-	RegenerateCgo           Command = "regenerate_cgo"
-	RemoveDependency        Command = "remove_dependency"
-	ResetGoModDiagnostics   Command = "reset_go_mod_diagnostics"
-	RunGoWorkCommand        Command = "run_go_work_command"
-	RunGovulncheck          Command = "run_govulncheck"
-	RunTests                Command = "run_tests"
-	StartDebugging          Command = "start_debugging"
-	StartProfile            Command = "start_profile"
-	StopProfile             Command = "stop_profile"
-	Test                    Command = "test"
-	Tidy                    Command = "tidy"
-	ToggleGCDetails         Command = "toggle_gc_details"
-	UpdateGoSum             Command = "update_go_sum"
-	UpgradeDependency       Command = "upgrade_dependency"
-	Vendor                  Command = "vendor"
-	Views                   Command = "views"
-	WorkspaceStats          Command = "workspace_stats"
+	AddDependency           Command = "gopls.add_dependency"
+	AddImport               Command = "gopls.add_import"
+	AddTelemetryCounters    Command = "gopls.add_telemetry_counters"
+	ApplyFix                Command = "gopls.apply_fix"
+	ChangeSignature         Command = "gopls.change_signature"
+	CheckUpgrades           Command = "gopls.check_upgrades"
+	DiagnoseFiles           Command = "gopls.diagnose_files"
+	Doc                     Command = "gopls.doc"
+	EditGoDirective         Command = "gopls.edit_go_directive"
+	FetchVulncheckResult    Command = "gopls.fetch_vulncheck_result"
+	FreeSymbols             Command = "gopls.free_symbols"
+	GCDetails               Command = "gopls.gc_details"
+	Generate                Command = "gopls.generate"
+	GoGetPackage            Command = "gopls.go_get_package"
+	ListImports             Command = "gopls.list_imports"
+	ListKnownPackages       Command = "gopls.list_known_packages"
+	MaybePromptForTelemetry Command = "gopls.maybe_prompt_for_telemetry"
+	MemStats                Command = "gopls.mem_stats"
+	RegenerateCgo           Command = "gopls.regenerate_cgo"
+	RemoveDependency        Command = "gopls.remove_dependency"
+	ResetGoModDiagnostics   Command = "gopls.reset_go_mod_diagnostics"
+	RunGoWorkCommand        Command = "gopls.run_go_work_command"
+	RunGovulncheck          Command = "gopls.run_govulncheck"
+	RunTests                Command = "gopls.run_tests"
+	StartDebugging          Command = "gopls.start_debugging"
+	StartProfile            Command = "gopls.start_profile"
+	StopProfile             Command = "gopls.stop_profile"
+	Test                    Command = "gopls.test"
+	Tidy                    Command = "gopls.tidy"
+	ToggleGCDetails         Command = "gopls.toggle_gc_details"
+	UpdateGoSum             Command = "gopls.update_go_sum"
+	UpgradeDependency       Command = "gopls.upgrade_dependency"
+	Vendor                  Command = "gopls.vendor"
+	Views                   Command = "gopls.views"
+	WorkspaceStats          Command = "gopls.workspace_stats"
 )
 
 var Commands = []Command{
@@ -98,163 +100,163 @@
 }
 
 func Dispatch(ctx context.Context, params *protocol.ExecuteCommandParams, s Interface) (interface{}, error) {
-	switch params.Command {
-	case "gopls.add_dependency":
+	switch Command(params.Command) {
+	case AddDependency:
 		var a0 DependencyArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return nil, s.AddDependency(ctx, a0)
-	case "gopls.add_import":
+	case AddImport:
 		var a0 AddImportArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return nil, s.AddImport(ctx, a0)
-	case "gopls.add_telemetry_counters":
+	case AddTelemetryCounters:
 		var a0 AddTelemetryCountersArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return nil, s.AddTelemetryCounters(ctx, a0)
-	case "gopls.apply_fix":
+	case ApplyFix:
 		var a0 ApplyFixArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return s.ApplyFix(ctx, a0)
-	case "gopls.change_signature":
+	case ChangeSignature:
 		var a0 ChangeSignatureArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return s.ChangeSignature(ctx, a0)
-	case "gopls.check_upgrades":
+	case CheckUpgrades:
 		var a0 CheckUpgradesArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return nil, s.CheckUpgrades(ctx, a0)
-	case "gopls.diagnose_files":
+	case DiagnoseFiles:
 		var a0 DiagnoseFilesArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return nil, s.DiagnoseFiles(ctx, a0)
-	case "gopls.doc":
+	case Doc:
 		var a0 protocol.Location
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return nil, s.Doc(ctx, a0)
-	case "gopls.edit_go_directive":
+	case EditGoDirective:
 		var a0 EditGoDirectiveArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return nil, s.EditGoDirective(ctx, a0)
-	case "gopls.fetch_vulncheck_result":
+	case FetchVulncheckResult:
 		var a0 URIArg
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return s.FetchVulncheckResult(ctx, a0)
-	case "gopls.free_symbols":
+	case FreeSymbols:
 		var a0 protocol.DocumentURI
 		var a1 protocol.Range
 		if err := UnmarshalArgs(params.Arguments, &a0, &a1); err != nil {
 			return nil, err
 		}
 		return nil, s.FreeSymbols(ctx, a0, a1)
-	case "gopls.gc_details":
+	case GCDetails:
 		var a0 protocol.DocumentURI
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return nil, s.GCDetails(ctx, a0)
-	case "gopls.generate":
+	case Generate:
 		var a0 GenerateArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return nil, s.Generate(ctx, a0)
-	case "gopls.go_get_package":
+	case GoGetPackage:
 		var a0 GoGetPackageArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return nil, s.GoGetPackage(ctx, a0)
-	case "gopls.list_imports":
+	case ListImports:
 		var a0 URIArg
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return s.ListImports(ctx, a0)
-	case "gopls.list_known_packages":
+	case ListKnownPackages:
 		var a0 URIArg
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return s.ListKnownPackages(ctx, a0)
-	case "gopls.maybe_prompt_for_telemetry":
+	case MaybePromptForTelemetry:
 		return nil, s.MaybePromptForTelemetry(ctx)
-	case "gopls.mem_stats":
+	case MemStats:
 		return s.MemStats(ctx)
-	case "gopls.regenerate_cgo":
+	case RegenerateCgo:
 		var a0 URIArg
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return nil, s.RegenerateCgo(ctx, a0)
-	case "gopls.remove_dependency":
+	case RemoveDependency:
 		var a0 RemoveDependencyArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return nil, s.RemoveDependency(ctx, a0)
-	case "gopls.reset_go_mod_diagnostics":
+	case ResetGoModDiagnostics:
 		var a0 ResetGoModDiagnosticsArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return nil, s.ResetGoModDiagnostics(ctx, a0)
-	case "gopls.run_go_work_command":
+	case RunGoWorkCommand:
 		var a0 RunGoWorkArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return nil, s.RunGoWorkCommand(ctx, a0)
-	case "gopls.run_govulncheck":
+	case RunGovulncheck:
 		var a0 VulncheckArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return s.RunGovulncheck(ctx, a0)
-	case "gopls.run_tests":
+	case RunTests:
 		var a0 RunTestsArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return nil, s.RunTests(ctx, a0)
-	case "gopls.start_debugging":
+	case StartDebugging:
 		var a0 DebuggingArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return s.StartDebugging(ctx, a0)
-	case "gopls.start_profile":
+	case StartProfile:
 		var a0 StartProfileArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return s.StartProfile(ctx, a0)
-	case "gopls.stop_profile":
+	case StopProfile:
 		var a0 StopProfileArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return s.StopProfile(ctx, a0)
-	case "gopls.test":
+	case Test:
 		var a0 protocol.DocumentURI
 		var a1 []string
 		var a2 []string
@@ -262,39 +264,39 @@
 			return nil, err
 		}
 		return nil, s.Test(ctx, a0, a1, a2)
-	case "gopls.tidy":
+	case Tidy:
 		var a0 URIArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return nil, s.Tidy(ctx, a0)
-	case "gopls.toggle_gc_details":
+	case ToggleGCDetails:
 		var a0 URIArg
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return nil, s.ToggleGCDetails(ctx, a0)
-	case "gopls.update_go_sum":
+	case UpdateGoSum:
 		var a0 URIArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return nil, s.UpdateGoSum(ctx, a0)
-	case "gopls.upgrade_dependency":
+	case UpgradeDependency:
 		var a0 DependencyArgs
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return nil, s.UpgradeDependency(ctx, a0)
-	case "gopls.vendor":
+	case Vendor:
 		var a0 URIArg
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
 			return nil, err
 		}
 		return nil, s.Vendor(ctx, a0)
-	case "gopls.views":
+	case Views:
 		return s.Views(ctx)
-	case "gopls.workspace_stats":
+	case WorkspaceStats:
 		return s.WorkspaceStats(ctx)
 	}
 	return nil, fmt.Errorf("unsupported command %q", params.Command)
@@ -307,7 +309,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.add_dependency",
+		Command:   AddDependency.String(),
 		Arguments: args,
 	}, nil
 }
@@ -319,7 +321,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.add_import",
+		Command:   AddImport.String(),
 		Arguments: args,
 	}, nil
 }
@@ -331,7 +333,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.add_telemetry_counters",
+		Command:   AddTelemetryCounters.String(),
 		Arguments: args,
 	}, nil
 }
@@ -343,7 +345,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.apply_fix",
+		Command:   ApplyFix.String(),
 		Arguments: args,
 	}, nil
 }
@@ -355,7 +357,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.change_signature",
+		Command:   ChangeSignature.String(),
 		Arguments: args,
 	}, nil
 }
@@ -367,7 +369,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.check_upgrades",
+		Command:   CheckUpgrades.String(),
 		Arguments: args,
 	}, nil
 }
@@ -379,7 +381,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.diagnose_files",
+		Command:   DiagnoseFiles.String(),
 		Arguments: args,
 	}, nil
 }
@@ -391,7 +393,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.doc",
+		Command:   Doc.String(),
 		Arguments: args,
 	}, nil
 }
@@ -403,7 +405,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.edit_go_directive",
+		Command:   EditGoDirective.String(),
 		Arguments: args,
 	}, nil
 }
@@ -415,7 +417,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.fetch_vulncheck_result",
+		Command:   FetchVulncheckResult.String(),
 		Arguments: args,
 	}, nil
 }
@@ -427,7 +429,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.free_symbols",
+		Command:   FreeSymbols.String(),
 		Arguments: args,
 	}, nil
 }
@@ -439,7 +441,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.gc_details",
+		Command:   GCDetails.String(),
 		Arguments: args,
 	}, nil
 }
@@ -451,7 +453,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.generate",
+		Command:   Generate.String(),
 		Arguments: args,
 	}, nil
 }
@@ -463,7 +465,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.go_get_package",
+		Command:   GoGetPackage.String(),
 		Arguments: args,
 	}, nil
 }
@@ -475,7 +477,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.list_imports",
+		Command:   ListImports.String(),
 		Arguments: args,
 	}, nil
 }
@@ -487,7 +489,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.list_known_packages",
+		Command:   ListKnownPackages.String(),
 		Arguments: args,
 	}, nil
 }
@@ -499,7 +501,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.maybe_prompt_for_telemetry",
+		Command:   MaybePromptForTelemetry.String(),
 		Arguments: args,
 	}, nil
 }
@@ -511,7 +513,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.mem_stats",
+		Command:   MemStats.String(),
 		Arguments: args,
 	}, nil
 }
@@ -523,7 +525,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.regenerate_cgo",
+		Command:   RegenerateCgo.String(),
 		Arguments: args,
 	}, nil
 }
@@ -535,7 +537,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.remove_dependency",
+		Command:   RemoveDependency.String(),
 		Arguments: args,
 	}, nil
 }
@@ -547,7 +549,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.reset_go_mod_diagnostics",
+		Command:   ResetGoModDiagnostics.String(),
 		Arguments: args,
 	}, nil
 }
@@ -559,7 +561,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.run_go_work_command",
+		Command:   RunGoWorkCommand.String(),
 		Arguments: args,
 	}, nil
 }
@@ -571,7 +573,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.run_govulncheck",
+		Command:   RunGovulncheck.String(),
 		Arguments: args,
 	}, nil
 }
@@ -583,7 +585,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.run_tests",
+		Command:   RunTests.String(),
 		Arguments: args,
 	}, nil
 }
@@ -595,7 +597,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.start_debugging",
+		Command:   StartDebugging.String(),
 		Arguments: args,
 	}, nil
 }
@@ -607,7 +609,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.start_profile",
+		Command:   StartProfile.String(),
 		Arguments: args,
 	}, nil
 }
@@ -619,7 +621,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.stop_profile",
+		Command:   StopProfile.String(),
 		Arguments: args,
 	}, nil
 }
@@ -631,7 +633,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.test",
+		Command:   Test.String(),
 		Arguments: args,
 	}, nil
 }
@@ -643,7 +645,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.tidy",
+		Command:   Tidy.String(),
 		Arguments: args,
 	}, nil
 }
@@ -655,7 +657,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.toggle_gc_details",
+		Command:   ToggleGCDetails.String(),
 		Arguments: args,
 	}, nil
 }
@@ -667,7 +669,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.update_go_sum",
+		Command:   UpdateGoSum.String(),
 		Arguments: args,
 	}, nil
 }
@@ -679,7 +681,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.upgrade_dependency",
+		Command:   UpgradeDependency.String(),
 		Arguments: args,
 	}, nil
 }
@@ -691,7 +693,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.vendor",
+		Command:   Vendor.String(),
 		Arguments: args,
 	}, nil
 }
@@ -703,7 +705,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.views",
+		Command:   Views.String(),
 		Arguments: args,
 	}, nil
 }
@@ -715,7 +717,7 @@
 	}
 	return protocol.Command{
 		Title:     title,
-		Command:   "gopls.workspace_stats",
+		Command:   WorkspaceStats.String(),
 		Arguments: args,
 	}, nil
 }
diff --git a/gopls/internal/protocol/command/commandmeta/meta.go b/gopls/internal/protocol/command/commandmeta/meta.go
index db66bb3..d9a5d27 100644
--- a/gopls/internal/protocol/command/commandmeta/meta.go
+++ b/gopls/internal/protocol/command/commandmeta/meta.go
@@ -23,19 +23,14 @@
 
 // A Command describes a workspace/executeCommand extension command.
 type Command struct {
-	MethodName string
-	Name       string
-	// TODO(rFindley): I think Title can actually be eliminated. In all cases
-	// where we use it, there is probably a more appropriate contextual title.
-	Title  string
-	Doc    string
-	Args   []*Field
-	Result *Field
+	MethodName string // e.g. "RunTests"
+	Name       string // e.g. "gopls.run_tests"
+	Title      string
+	Doc        string
+	Args       []*Field
+	Result     *Field
 }
 
-// (used by the ../command/gen template)
-func (c *Command) ID() string { return "gopls." + c.Name }
-
 type Field struct {
 	Name     string
 	Doc      string
@@ -208,7 +203,7 @@
 	for i := range words {
 		words[i] = strings.ToLower(words[i])
 	}
-	return strings.Join(words, "_")
+	return "gopls." + strings.Join(words, "_")
 }
 
 // splitCamel splits s into words, according to camel-case word boundaries.
diff --git a/gopls/internal/protocol/command/gen/gen.go b/gopls/internal/protocol/command/gen/gen.go
index fadb12a..8ae50f6 100644
--- a/gopls/internal/protocol/command/gen/gen.go
+++ b/gopls/internal/protocol/command/gen/gen.go
@@ -35,9 +35,11 @@
 	{{end}}
 )
 
-// Symbolic names for gopls commands, excluding "gopls." prefix.
-// These commands may be requested by ExecuteCommand, CodeLens,
-// CodeAction, and other LSP requests.
+// Symbolic names for gopls commands, corresponding to methods of [Interface].
+//
+// The string value is used in the Command field of protocol.Command.
+// These commands may be obtained from a CodeLens or CodeAction request
+// and executed by an ExecuteCommand request.
 const (
 {{- range .Commands}}
 	{{.MethodName}} Command = "{{.Name}}"
@@ -51,9 +53,9 @@
 }
 
 func Dispatch(ctx context.Context, params *protocol.ExecuteCommandParams, s Interface) (interface{}, error) {
-	switch params.Command {
+	switch Command(params.Command) {
 	{{- range .Commands}}
-	case "{{.ID}}":
+	case {{.MethodName}}:
 		{{- if .Args -}}
 			{{- range $i, $v := .Args}}
 		var a{{$i}} {{typeString $v.Type}}
@@ -76,7 +78,7 @@
 	}
 	return protocol.Command{
 		Title: title,
-		Command: "{{.ID}}",
+		Command: {{.MethodName}}.String(),
 		Arguments: args,
 	}, nil
 }
diff --git a/gopls/internal/protocol/command/interface.go b/gopls/internal/protocol/command/interface.go
index 0934cf2..e8d6d7d 100644
--- a/gopls/internal/protocol/command/interface.go
+++ b/gopls/internal/protocol/command/interface.go
@@ -29,9 +29,8 @@
 //  1. All method arguments must be JSON serializable.
 //  2. Methods must return either error or (T, error), where T is a
 //     JSON serializable type.
-//  3. The first line of the doc string is special. Everything after the colon
-//     is considered the command 'Title'.
-//     TODO(rFindley): reconsider this -- Title may be unnecessary.
+//  3. The first line of the doc string is special.
+//     Everything after the colon is considered the command 'Title'.
 //
 // The doc comment on each method is eventually published at
 // https://github.com/golang/tools/blob/master/gopls/doc/commands.md,
diff --git a/gopls/internal/protocol/command/util.go b/gopls/internal/protocol/command/util.go
index 0d9799f..b403679 100644
--- a/gopls/internal/protocol/command/util.go
+++ b/gopls/internal/protocol/command/util.go
@@ -9,35 +9,24 @@
 	"fmt"
 )
 
-// TODO(adonovan): use the "gopls."-prefix forms everywhere. The
-// existence of two forms is a nuisance. I think it should be a
-// straightforward fix, as all public APIs and docs use that form
-// already.
-
-// ID returns the command name for use in the LSP.
-func ID(name string) string {
-	return "gopls." + name
-}
-
+// A Command identifies one of gopls' ad-hoc extension commands
+// that may be invoked through LSP's executeCommand.
 type Command string
 
+func (c Command) String() string { return string(c) }
+
 // IsAsync reports whether the command is asynchronous:
 // clients must wait for the "end" progress notification.
 func (c Command) IsAsync() bool {
 	switch string(c) {
 	// TODO(adonovan): derive this list from interface.go somewhow.
 	// Unfortunately we can't even reference the enum from here...
-	case "run_tests", "run_govulncheck", "test":
+	case "gopls.run_tests", "gopls.run_govulncheck", "gopls.test":
 		return true
 	}
 	return false
 }
 
-// ID returns the command identifier to use in the executeCommand request.
-func (c Command) ID() string {
-	return ID(string(c))
-}
-
 // MarshalArgs encodes the given arguments to json.RawMessages. This function
 // is used to construct arguments to a protocol.Command.
 //
diff --git a/gopls/internal/server/command.go b/gopls/internal/server/command.go
index ad2eb95..0a64d1c 100644
--- a/gopls/internal/server/command.go
+++ b/gopls/internal/server/command.go
@@ -187,8 +187,7 @@
 		return err
 	}
 
-	enum := command.Command(strings.TrimPrefix(c.params.Command, "gopls."))
-	if enum.IsAsync() {
+	if enum := command.Command(c.params.Command); enum.IsAsync() {
 		if cfg.progress == "" {
 			log.Fatalf("asynchronous command %q does not enable progress reporting",
 				enum)
diff --git a/gopls/internal/settings/default.go b/gopls/internal/settings/default.go
index 56dce7e..e280c75 100644
--- a/gopls/internal/settings/default.go
+++ b/gopls/internal/settings/default.go
@@ -27,7 +27,7 @@
 	optionsOnce.Do(func() {
 		var commands []string
 		for _, c := range command.Commands {
-			commands = append(commands, c.ID())
+			commands = append(commands, c.String())
 		}
 		defaultOptions = &Options{
 			ClientOptions: ClientOptions{
diff --git a/gopls/internal/telemetry/telemetry_test.go b/gopls/internal/telemetry/telemetry_test.go
index d2eecdf..6c1944b 100644
--- a/gopls/internal/telemetry/telemetry_test.go
+++ b/gopls/internal/telemetry/telemetry_test.go
@@ -123,11 +123,11 @@
 	}
 	var res error
 	env.ExecuteCommand(&protocol.ExecuteCommandParams{
-		Command:   command.AddTelemetryCounters.ID(),
+		Command:   command.AddTelemetryCounters.String(),
 		Arguments: args,
 	}, &res)
 	if res != nil {
-		env.T.Errorf("%v failed - %v", command.AddTelemetryCounters.ID(), res)
+		env.T.Errorf("%v failed - %v", command.AddTelemetryCounters, res)
 	}
 }
 
diff --git a/gopls/internal/test/integration/bench/bench_test.go b/gopls/internal/test/integration/bench/bench_test.go
index a04c63d..5de6804 100644
--- a/gopls/internal/test/integration/bench/bench_test.go
+++ b/gopls/internal/test/integration/bench/bench_test.go
@@ -288,7 +288,7 @@
 // the profile is written to a temp file that is deleted after the cpu_seconds
 // metric has been computed.
 func startProfileIfSupported(b *testing.B, env *integration.Env, name string) func() {
-	if !env.Editor.HasCommand(command.StartProfile.ID()) {
+	if !env.Editor.HasCommand(command.StartProfile) {
 		return nil
 	}
 	b.StopTimer()
diff --git a/gopls/internal/test/integration/bench/iwl_test.go b/gopls/internal/test/integration/bench/iwl_test.go
index 07a5d90..ecf26f9 100644
--- a/gopls/internal/test/integration/bench/iwl_test.go
+++ b/gopls/internal/test/integration/bench/iwl_test.go
@@ -57,10 +57,10 @@
 
 	env.Await(InitialWorkspaceLoad)
 
-	if env.Editor.HasCommand(command.MemStats.ID()) {
+	if env.Editor.HasCommand(command.MemStats) {
 		b.StopTimer()
 		params := &protocol.ExecuteCommandParams{
-			Command: command.MemStats.ID(),
+			Command: command.MemStats.String(),
 		}
 		var memstats command.MemStatsResult
 		env.ExecuteCommand(params, &memstats)
diff --git a/gopls/internal/test/integration/codelens/codelens_test.go b/gopls/internal/test/integration/codelens/codelens_test.go
index 399b8d3..800856d 100644
--- a/gopls/internal/test/integration/codelens/codelens_test.go
+++ b/gopls/internal/test/integration/codelens/codelens_test.go
@@ -54,7 +54,7 @@
 		},
 		{
 			label:        "generate disabled",
-			enabled:      map[string]bool{string(command.Generate): false},
+			enabled:      map[string]bool{string(protocol.CodeLensGenerate): false},
 			wantCodeLens: false,
 		},
 	}
diff --git a/gopls/internal/test/integration/codelens/gcdetails_test.go b/gopls/internal/test/integration/codelens/gcdetails_test.go
index 1ac3a88..359a780 100644
--- a/gopls/internal/test/integration/codelens/gcdetails_test.go
+++ b/gopls/internal/test/integration/codelens/gcdetails_test.go
@@ -101,7 +101,7 @@
 		hasGCDetails := func() bool {
 			lenses := env.CodeLens("p_test.go") // should not crash
 			for _, lens := range lenses {
-				if lens.Command.Command == command.GCDetails.ID() {
+				if lens.Command.Command == command.GCDetails.String() {
 					return true
 				}
 			}
diff --git a/gopls/internal/test/integration/debug/debug_test.go b/gopls/internal/test/integration/debug/debug_test.go
index 3b43de9..1dccea4 100644
--- a/gopls/internal/test/integration/debug/debug_test.go
+++ b/gopls/internal/test/integration/debug/debug_test.go
@@ -80,7 +80,7 @@
 		return nil, err
 	}
 	res0, err := server.ExecuteCommand(ctx, &protocol.ExecuteCommandParams{
-		Command:   command.StartDebugging.ID(),
+		Command:   command.StartDebugging.String(),
 		Arguments: rawArgs,
 	})
 	if err != nil {
diff --git a/gopls/internal/test/integration/fake/editor.go b/gopls/internal/test/integration/fake/editor.go
index 36354d5..f5d62b0 100644
--- a/gopls/internal/test/integration/fake/editor.go
+++ b/gopls/internal/test/integration/fake/editor.go
@@ -391,9 +391,9 @@
 }
 
 // HasCommand reports whether the connected server supports the command with the given ID.
-func (e *Editor) HasCommand(id string) bool {
+func (e *Editor) HasCommand(cmd command.Command) bool {
 	for _, command := range e.serverCapabilities.ExecuteCommandProvider.Commands {
-		if command == id {
+		if command == cmd.String() {
 			return true
 		}
 	}
diff --git a/gopls/internal/test/integration/misc/debugserver_test.go b/gopls/internal/test/integration/misc/debugserver_test.go
index d1ce21b..87f892f 100644
--- a/gopls/internal/test/integration/misc/debugserver_test.go
+++ b/gopls/internal/test/integration/misc/debugserver_test.go
@@ -23,7 +23,7 @@
 			t.Fatal(err)
 		}
 		params := &protocol.ExecuteCommandParams{
-			Command:   command.StartDebugging.ID(),
+			Command:   command.StartDebugging.String(),
 			Arguments: args,
 		}
 		var result command.DebuggingResult
diff --git a/gopls/internal/test/integration/misc/import_test.go b/gopls/internal/test/integration/misc/import_test.go
index 0df3f8d..af933b1 100644
--- a/gopls/internal/test/integration/misc/import_test.go
+++ b/gopls/internal/test/integration/misc/import_test.go
@@ -121,7 +121,7 @@
 			}
 			var result command.ListImportsResult
 			env.ExecuteCommand(&protocol.ExecuteCommandParams{
-				Command:   command.ListImports.ID(),
+				Command:   command.ListImports.String(),
 				Arguments: cmd.Arguments,
 			}, &result)
 			if diff := cmp.Diff(tt.want, result); diff != "" {
diff --git a/gopls/internal/test/integration/misc/vuln_test.go b/gopls/internal/test/integration/misc/vuln_test.go
index f47d06a..6ba1ec8 100644
--- a/gopls/internal/test/integration/misc/vuln_test.go
+++ b/gopls/internal/test/integration/misc/vuln_test.go
@@ -41,7 +41,7 @@
 		}
 
 		params := &protocol.ExecuteCommandParams{
-			Command:   command.RunGovulncheck.ID(),
+			Command:   command.RunGovulncheck.String(),
 			Arguments: cmd.Arguments,
 		}
 
diff --git a/gopls/internal/test/integration/wrappers.go b/gopls/internal/test/integration/wrappers.go
index 55b99ea..0982f8a 100644
--- a/gopls/internal/test/integration/wrappers.go
+++ b/gopls/internal/test/integration/wrappers.go
@@ -355,13 +355,13 @@
 	var lens protocol.CodeLens
 	var found bool
 	for _, l := range lenses {
-		if l.Command.Command == cmd.ID() {
+		if l.Command.Command == cmd.String() {
 			lens = l
 			found = true
 		}
 	}
 	if !found {
-		e.T.Fatalf("found no command with the ID %s", cmd.ID())
+		e.T.Fatalf("found no command with the ID %s", cmd)
 	}
 	e.ExecuteCommand(&protocol.ExecuteCommandParams{
 		Command:   lens.Command.Command,
@@ -421,7 +421,7 @@
 		e.T.Fatal(err)
 	}
 	params := &protocol.ExecuteCommandParams{
-		Command:   command.StartProfile.ID(),
+		Command:   command.StartProfile.String(),
 		Arguments: args,
 	}
 	var result command.StartProfileResult
@@ -433,7 +433,7 @@
 			e.T.Fatal(err)
 		}
 		stopParams := &protocol.ExecuteCommandParams{
-			Command:   command.StopProfile.ID(),
+			Command:   command.StopProfile.String(),
 			Arguments: stopArgs,
 		}
 		var result command.StopProfileResult