cmd/internal/pkgsite-cli: move the design memo to the package dir

This change will make the memo shown in pkgsite.
Also apply minor polishing of help message and source code documentation.

Change-Id: Ia26e705171aea9d649e3469ad14ba256ba044ebc
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/781241
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Ethan Lee <ethanalee@google.com>
kokoro-CI: kokoro <noreply+kokoro@google.com>
diff --git a/cmd/internal/pkgsite-cli/README.md b/cmd/internal/pkgsite-cli/README.md
new file mode 100644
index 0000000..7b8c397
--- /dev/null
+++ b/cmd/internal/pkgsite-cli/README.md
@@ -0,0 +1,113 @@
+# pkgsite-cli
+
+A command-line interface for querying [pkg.go.dev](https://pkg.go.dev/).
+
+Currently, the API is on `v1beta`, but we expect to move to `v1` soon.
+
+Related to issue [76718](https://go.dev/issue/76718).
+
+## Quick start
+
+To install the `pkgsite-cli` tool, run:
+
+```bash
+go install golang.org/x/pkgsite/cmd/internal/pkgsite-cli@latest
+```
+
+## Motivation
+
+The [pkg.go.dev](https://pkg.go.dev/) service provides an API interface at
+https://pkg.go.dev/api to allow querying information about published Go
+packages and modules. The API uses a stateless, GET-only architecture designed
+for stability and efficient caching. `pkgsite-cli` is a lightweight CLI that
+uses this API. There is no official SDK for the API, but this tool serves as a
+reference client implementation that developers can use in other projects. See
+the [API spec](https://pkg.go.dev/api) and the
+[OpenAPI specification](https://pkg.go.dev/v1beta/openapi.yaml).
+
+## Relationship to existing tools
+
+- **`go doc`** renders documentation for packages available locally.
+  `pkgsite-cli` does not replace it for reading local documentation.
+- **`cmd/pkgsite`** is a web server that serves documentation for packages
+  available locally. It does not provide full version listings, vulnerability
+  reports, reverse dependencies, licenses, or search capabilities (yet).
+- **`pkgsite-cli`** provides access to information that `go doc` or a local
+  instance of `cmd/pkgsite` cannot reach: version listings, vulnerability
+  reports, reverse dependencies, licenses, documentation of modules/packages,
+  and search results for packages not yet downloaded.
+
+Rule of thumb: Use `go doc` for local code; use `pkgsite-cli` for package
+discovery and metadata lookup.
+
+## Commands
+
+Run `pkgsite-cli <command> -h` for details on available flags for each command.
+
+Available commands:
+ * `package`
+ * `module`
+ * `search`
+
+Additional commands will be added in the future.
+
+## Usage Examples
+
+### Search for packages:
+
+```bash
+pkgsite-cli search uuid
+```
+
+### Inspect a specific package:
+
+```bash
+pkgsite-cli package github.com/google/go-cmp/cmp
+```
+
+### See reverse dependencies for a package:
+
+```bash
+pkgsite-cli package -imported-by github.com/google/go-cmp/cmp
+```
+
+### List exported symbols declared by a package:
+
+```bash
+pkgsite-cli package -symbols github.com/google/go-cmp/cmp
+```
+
+### List versions of a module:
+
+```bash
+pkgsite-cli module -versions github.com/google/go-cmp
+```
+
+### List both versions and packages belonging to a module:
+
+```bash
+pkgsite-cli module -packages -versions github.com/google/go-cmp
+```
+
+## Details
+- **Ambiguous paths**: Unlike `go mod tidy` or the
+  [pkg.go.dev](https://pkg.go.dev) web interface, which use the "longest
+  module path" rule to resolve ambiguous package paths, the API requires the
+  module to be specified unambiguously. If a package path is ambiguous
+  because it exists in multiple modules, the API returns a list of candidates
+  and reports an error. Use the `-module` flag to specify the correct
+  module path.
+
+
+## Status and Implementation
+- **Experimental**: This tool is currently a prototype.
+- **Minimal Dependencies**: To facilitate potential migration to other
+  repositories (e.g., `x/tools`), the tool depends only on the Go standard
+  library.
+- **Duplicate Types**: API request and response types are duplicated in the
+  tool's source instead of imported from `pkgsite` for now. We ruled out
+  releasing a full SDK because the REST API is simple enough to consume
+  directly. This keeps the tool self-contained. However, if this tool remains
+  in this repository, we can eliminate this duplication by using the internal
+  package.
+
diff --git a/cmd/internal/pkgsite-cli/client/client.go b/cmd/internal/pkgsite-cli/client/client.go
index e78b26f..f4b6553 100644
--- a/cmd/internal/pkgsite-cli/client/client.go
+++ b/cmd/internal/pkgsite-cli/client/client.go
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// Package client provides a client for the pkg.go.dev v1beta API.
 package client
 
 //go:generate go test -run=TestTypesUpToDate -update
@@ -166,6 +167,7 @@
 	GOARCH   string
 }
 
+// GetPackage fetches package information for the given path and version.
 func (c *Client) GetPackage(ctx context.Context, path, version string, opts PackageOptions) (*Package, error) {
 	q := make(url.Values)
 	if version != "" {
@@ -216,6 +218,7 @@
 	PaginationOptions
 }
 
+// GetSymbols fetches symbols for the given package path and version.
 func (c *Client) GetSymbols(ctx context.Context, path, version string, opts SymbolsOptions) (*PaginatedResponse[Symbol], error) {
 	q := make(url.Values)
 	if version != "" {
@@ -251,6 +254,7 @@
 	PaginationOptions
 }
 
+// GetImportedBy fetches packages that import the given package path and version.
 func (c *Client) GetImportedBy(ctx context.Context, path, version string, opts ImportedByOptions) (*PackageImportedBy, error) {
 	q := make(url.Values)
 	if version != "" {
@@ -280,6 +284,7 @@
 	Licenses bool
 }
 
+// GetModule fetches module information for the given path and version.
 func (c *Client) GetModule(ctx context.Context, path, version string, opts ModuleOptions) (*Module, error) {
 	q := make(url.Values)
 	if version != "" {
@@ -305,6 +310,7 @@
 	Version string `json:"version"`
 }
 
+// GetVersions fetches a list of versions for the given module path.
 func (c *Client) GetVersions(ctx context.Context, path string, opts PaginationOptions) (*PaginatedResponse[VersionResponse], error) {
 	q := make(url.Values)
 	if opts.Limit > 0 {
@@ -322,6 +328,7 @@
 	return &resp, nil
 }
 
+// GetVulns fetches a list of vulnerabilities for the given module path and version.
 func (c *Client) GetVulns(ctx context.Context, path, version string, opts PaginationOptions) (*PaginatedResponse[Vulnerability], error) {
 	q := make(url.Values)
 	if version != "" {
@@ -348,6 +355,7 @@
 	Synopsis string `json:"synopsis"`
 }
 
+// GetPackages fetches a list of packages for the given module path and version.
 func (c *Client) GetPackages(ctx context.Context, modulePath, version string, opts PaginationOptions) (*PaginatedResponse[ModulePackageResponse], error) {
 	q := make(url.Values)
 	if version != "" {
@@ -385,6 +393,7 @@
 	PaginationOptions
 }
 
+// Search queries the pkg.go.dev API for packages matching the given query.
 func (c *Client) Search(ctx context.Context, query string, opts SearchOptions) (*PaginatedResponse[SearchResult], error) {
 	q := make(url.Values)
 	q.Set("q", query)
diff --git a/cmd/internal/pkgsite-cli/command.go b/cmd/internal/pkgsite-cli/command.go
index 16160f1..94dc6d5 100644
--- a/cmd/internal/pkgsite-cli/command.go
+++ b/cmd/internal/pkgsite-cli/command.go
@@ -53,12 +53,13 @@
 
 // printUsage writes usage for all commands to w.
 func printUsage(w io.Writer, cmds []*command) {
+	fmt.Fprintf(w, "%s queries the pkg.go.dev API for information about Go packages and modules.\n\n", filepath.Base(os.Args[0]))
 	fmt.Fprintln(w, "Usage:")
 	for _, c := range cmds {
 		line := c.usageLine()
 		fmt.Fprintf(w, "  %-50s %s\n", line, c.summary)
 	}
-	fmt.Fprintf(w, "\nRun \"%s <command> -h\" for command-specific flags.\n", filepath.Base(os.Args[0]))
+	fmt.Fprintf(w, "\nRun \"%s <command> -h\" for details on available flags for each command.\n", filepath.Base(os.Args[0]))
 }
 
 // dispatch finds and runs the matching command. It returns the exit code.
diff --git a/cmd/internal/pkgsite-cli/main.go b/cmd/internal/pkgsite-cli/main.go
index 2cbbdc7..704583b 100644
--- a/cmd/internal/pkgsite-cli/main.go
+++ b/cmd/internal/pkgsite-cli/main.go
@@ -5,13 +5,13 @@
 // Command pkgsite-cli queries the pkg.go.dev API for information about
 // Go packages and modules.
 //
+// For more information, see https://go.dev/blog/pkgsite-api.
+//
 // Usage:
 //
-//	pkgsite-cli package <package>[@version] [flags]  package information
-//	pkgsite-cli module <module>[@version] [flags]      module information
-//	pkgsite-cli search <query> [flags]                 search for packages
-//
-// See doc/pkgsite-cli.md for the full design document.
+//	pkgsite-cli package <package>[@version] [flags]    Show package details.
+//	pkgsite-cli module <module>[@version] [flags]      Show module details.
+//	pkgsite-cli search <query> [flags]                 Search for packages.
 package main
 
 import (
@@ -57,7 +57,10 @@
 
 	pkgRun := func(fs *flag.FlagSet, stdout, stderr io.Writer) int { return runPackage(fs, &pf, stdout, stderr) }
 
-	const packageDoc = `
+	const packageDoc = `Queries information about a specific Go package from pkg.go.dev.
+By default, this prints basic metadata. Use flags to request additional
+information such as exported symbols, reverse dependencies, or rendered documentation.
+
 When using -json, the output is a JSON object with the following structure:
 
     type packageResult struct {
@@ -88,7 +91,10 @@
     }
 `
 
-	const moduleDoc = `
+	const moduleDoc = `Queries information about a specific Go module from pkg.go.dev.
+By default, this prints basic metadata. Use flags to request additional
+information such as versions, vulnerabilities, or packages contained in the module.
+
 When using -json, the output is a JSON object with the following structure:
 
     type moduleResult struct {
@@ -113,7 +119,9 @@
     }
 `
 
-	const searchDoc = `
+	const searchDoc = `Searches for Go packages on pkg.go.dev matching the given query.
+By default, this prints a list of matching packages with their synopsis.
+
 When using -json, the output is a JSON object with the following structure:
 
     type PaginatedResponse[SearchResult] struct {
@@ -135,7 +143,7 @@
 		{
 			name:        "package",
 			args:        "<package>[@version]",
-			summary:     "package information",
+			summary:     "Show package details",
 			description: strings.TrimSpace(packageDoc),
 			flags:       pkgFS,
 			run:         pkgRun,
@@ -143,7 +151,7 @@
 		{
 			name:        "module",
 			args:        "<module>[@version]",
-			summary:     "module information",
+			summary:     "Show module details",
 			description: strings.TrimSpace(moduleDoc),
 			flags:       modFS,
 			run:         func(fs *flag.FlagSet, stdout, stderr io.Writer) int { return runModule(fs, &mf, stdout, stderr) },
@@ -151,19 +159,19 @@
 		{
 			name:        "search",
 			args:        "<query>",
-			summary:     "search for packages",
+			summary:     "Search for packages",
 			description: strings.TrimSpace(searchDoc),
 			flags:       searchFS,
 			run:         func(fs *flag.FlagSet, stdout, stderr io.Writer) int { return runSearch(fs, &sf, stdout, stderr) },
 		},
 		{
 			name:    "help",
-			summary: "show this help message",
+			summary: "Show this help message",
 			run:     func(_ *flag.FlagSet, stdout, _ io.Writer) int { printUsage(stdout, cmds); return 0 },
 		},
 		{
 			name:    "version",
-			summary: "print version information",
+			summary: "Print version information",
 			run:     func(_ *flag.FlagSet, stdout, _ io.Writer) int { fmt.Fprintln(stdout, versionInfo()); return 0 },
 		},
 	}
diff --git a/cmd/internal/pkgsite-cli/module.go b/cmd/internal/pkgsite-cli/module.go
index 296b171..08aeaec 100644
--- a/cmd/internal/pkgsite-cli/module.go
+++ b/cmd/internal/pkgsite-cli/module.go
@@ -7,6 +7,7 @@
 import (
 	"context"
 	"flag"
+	"fmt"
 	"io"
 
 	"golang.org/x/pkgsite/cmd/internal/pkgsite-cli/client"
@@ -15,6 +16,7 @@
 
 func runModule(fs *flag.FlagSet, m *moduleFlags, stdout, stderr io.Writer) int {
 	if fs.NArg() != 1 {
+		fmt.Fprintf(stderr, "Error: expected exactly 1 module argument, got %d\n", fs.NArg())
 		fs.Usage()
 		return 2
 	}
diff --git a/cmd/internal/pkgsite-cli/search.go b/cmd/internal/pkgsite-cli/search.go
index 9e0d5d3..bf1866e 100644
--- a/cmd/internal/pkgsite-cli/search.go
+++ b/cmd/internal/pkgsite-cli/search.go
@@ -7,6 +7,7 @@
 import (
 	"context"
 	"flag"
+	"fmt"
 	"io"
 	"strings"
 
@@ -15,6 +16,7 @@
 
 func runSearch(fs *flag.FlagSet, s *searchFlags, stdout, stderr io.Writer) int {
 	if fs.NArg() < 1 {
+		fmt.Fprintln(stderr, "Error: expected at least 1 search query argument")
 		fs.Usage()
 		return 2
 	}
diff --git a/doc/pkgsite-cli.md b/doc/pkgsite-cli.md
deleted file mode 100644
index 19c2cc3..0000000
--- a/doc/pkgsite-cli.md
+++ /dev/null
@@ -1,82 +0,0 @@
-# pkgsite-cli
-
-A command-line interface for querying pkg.go.dev.
-
-Currently the API is on `v1beta`, but we expect to move to `v1` soon.
-
-Related to https://go.dev/issue/76718.
-
-## Quick start
-
-To install the `pkgsite-cli` tool, run:
-
-```bash
-go install golang.org/x/pkgsite/cmd/internal/pkgsite-cli@latest
-```
-
-## Motivation
-
-The pkg.go.dev service exposes a REST API for package and module metadata.
-(TODO: link to the API doc).
-`pkgsite-cli` provides a lightweight CLI that queries the API and
-prints results for both humans and automated tools.
-There is no official SDK for the API, but this tool serves as a reference
-client implementation that developers can use in other projects.
-
-## Relationship to existing tools
-
-- **`go doc`** renders documentation for packages available locally.
-  `pkgsite-cli` does not replace it for reading local documentation.
-- **`cmd/pkgsite`** is a webserver that serves documentation for packages
-  available locally. It does not provide full version listings, vulnerability
-  reports, reverse dependencies, licenses, or search capabilities (yet).
-- **`pkgsite-cli`** provides access to information `go doc` or a local instance
-  of `cmd/pkgsite` cannot reach: version listings, vulnerability reports, reverse
-  dependencies, licenses, documentation of modules/packages, and search
-  results for packages not yet downloaded.
-
-Rule of thumb: Use `go doc` for local code; use `pkgsite-cli`
-for package discovery and metadata lookup.
-
-## Commands
-
-Run `pkgsite-cli <command> -h` for details on available flags for each command.
-
-Available commands:
- * package
- * module
- * search
-
-More commands will be added.
-
-### Package info
-
-`pkgsite-cli package [flags] <package>[@version]`
-
-Example:
-```
-$ pkgsite-cli package encoding/json
-encoding/json (standard library)
-  Module:   std
-  Version:  go1.24.2 (latest)
-```
-
-### Module info
-`pkgsite-cli module [flags] <module>[@version]`
-
-### Search
-`pkgsite-cli search [flags] <query>`
-
-## Details
-- Ambiguous path: CLI shows candidates. Use `--module` to resolve.
-- Pagination: JSON returns `nextPageToken`. Use `--token` to continue.
-
-## Status and Implementation
-- **Experimental**: This tool is currently a prototype.
-- **Minimal Dependencies**: To facilitate potential migration to other repositories
-(e.g. `x/tools`), the tool depends only on the Go standard library.
-- **Duplicated Types**: API request/response types are duplicated in the tool's source
-  instead of imported from `pkgsite` for now.  We ruled out releasing a full SDK
-  because the REST API is simple enough to consume directly.
-  This keeps the tool self-contained.  If this tool remains in this repo,
-  however, we can eliminate this duplication and use the internal package.