Building a pkg.go.dev TUI explorer
The new API finally makes it practical to browse Go documentation entirely from anywhere.
For years, pkg.go.dev has been the central place to discover Go packages.
I genuinely like the project. The interface is clean, fast, and consistent. Unlike ecosystems such as npm, package authors don’t need to explicitly publish documentation anywhere—if your module is available through the Go module ecosystem, it’s already indexed.
The documentation is generated directly from source code downloaded via the Go Module Mirror, making it one of the most seamless documentation systems around.
For example, I maintain a PayPal SDK for Go, and it’s automatically available on pkg.go.dev without any extra publishing step.
https://pkg.go.dev/github.com/plutov/paypal/v4
Recently, the Go team took this one step further by launching the pkg.go.dev API.
Instead of scraping HTML or reverse-engineering the website, we now have direct programmatic access to package metadata, module versions, symbols, vulnerabilities, import relationships, and much more.
Even better, the API is published with an official OpenAPI specification.
https://pkg.go.dev/v1beta/openapi.yaml
That seemingly small detail changes everything. It means generating a Go client becomes almost effortless.
Why I Care
I spend most of my day inside Neovim.
Every time I need to open a browser just to look up package documentation, it breaks my flow. Switching contexts sounds insignificant until you do it dozens of times every day.
The new API finally makes it practical to browse Go documentation entirely from the terminal.
So I decided to build a small TUI (terminal UI) that lets me:
search packages
browse module versions
inspect exported symbols
extend it later with vulnerabilities, dependency information, and more
all without leaving the terminal.
Here is what’s we’re going to build:
Sponsor
AI writes more code than ever. Reviewing it shouldn’t mean scrolling forty files in alphabetical order.
CodeRabbit Review reorganizes any pull request from a flat file list into a structured, layer-by-layer walkthrough - the logical reading order of the change, not the order your platform happens to sort it. Every range gets its own plain-language summary, with sequence diagrams, state machines, and ERDs generated inline wherever a visual earns its place.
Cohorts group related files and chunks so you review one idea at a time. Layers order them so foundational changes - data shapes, contracts - come before the code that depends on them. Code Peek lets you click any variable, function, class or type to see its definition and usages without leaving the tab, while Semantic Diff view cuts past formatting noise to show what actually changed.
Open it straight from the Review Change Stack button in the PR Walkthrough. Navigate cohorts and layers from the keyboard, comment against exact line ranges and submit native reviews, comments and approvals post back to GitHub or GitLab right where your team expects them.
In the early access, available for free to everyone.
From the team that pioneered AI code reviews. 2M reviews every week. 6M repos. 15K customers.The review interface built for the way modern PRs are actually written.
Review your next PR with CodeRabbit Review Today
Exploring the API
The API exposes structured metadata through a collection of REST endpoints.
Some of the most useful ones are:
/search/package/module/versions/symbols/imported-by/vulns
Everything is read-only and designed to be cache-friendly.
For example, retrieving metadata for the cmp package is as simple as:
curl https://pkg.go.dev/v1beta/package/github.com/google/go-cmp/cmp | jqThe response includes information such as:
module path
package path
version
synopsis
redistributable status
The important part isn’t the JSON itself.
The important part is that we can now build tools on top of Go’s package ecosystem without scraping a single HTML page.
Generating an API Client
Since the API publishes an OpenAPI schema, generating a Go SDK is straightforward using oapi-codegen by Jamie Tanna.
https://github.com/oapi-codegen/oapi-codegen
I’ve previously made a video about oapi-codegen, so this project was a perfect excuse to use it again.
go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@latest
oapi-codegen \
-generate types,client \
-package pkgsiteapi \
pkgsiteapi/openapi.yaml > pkgsiteapi/client.gen.goThere was one small catch.
At the time I built this project, generating directly from the published OpenAPI URL didn’t work. The document itself contained a couple of issues:
some
{path}endpoints were missing their corresponding path parameter definitionsone schema reference was invalid
My workaround was simple: download the specification, fix the issues locally, and generate the client from that file instead.
I also noticed that some response types aren’t fully modeled. For example, the /search endpoint doesn’t map directly to a dedicated SearchResult type, so I had to extend the generated models myself.
Nothing impossible, but there is definitely room for improvement.
Building the TUI
For the interface I used Bubble Tea, which has become my default choice for terminal applications.
The application itself is intentionally minimal.
There are three areas of focus:
Search input
Search results
Package details
The model keeps track of the currently selected package along with the API responses.
ype Model struct {
client *pkgsiteapi.ClientWithResponses
input textinput.Model
viewport viewport.Model
results []pkgsiteapi.SearchResult
currItem *pkgsiteapi.SearchResult
versions *pkgsiteapi.PaginatedResponse
symbols *pkgsiteapi.PackageSymbols
loading bool
focus focusMode
}Bubble Tea’s architecture fits this kind of application nicely.
The UI reacts to messages:
a search completes
package details arrive
an error occurs
The Update() function becomes the event loop that coordinates everything, while the API calls live separately in commands.go.
The result is a clean separation between:
state
networking
rendering
which makes the application easy to extend later.
Btw, there is also a video me explaining the details of Bubble Tea.
Putting Everything Together
The entry point is pleasantly small.
After creating the generated API client, Bubble Tea takes over.
client, err := pkgsiteapi.NewClientWithResponses(apiBaseURL)
if _, err := tea.NewProgram(
newModel(client),
tea.WithAltScreen(),
).Run(); err != nil {
...
}Most of the complexity ends up living in the update loop rather than in main.go, which is exactly where it belongs.
Where This Can Go Next
The current application only scratches the surface of what’s available.
Because the API already exposes module versions, symbols, dependency information, and vulnerabilities, it wouldn’t take much to add features like:
vulnerability browsing
dependency trees
reverse dependency lookup
package bookmarking
offline caching
fuzzy search
documentation previews
The hard part—accessing structured package data—is already solved by the Go team.
Final Thoughts
I think this API is one of the more exciting additions to the Go tooling ecosystem in recent years.
It removes the need for scraping, provides an official machine-readable interface, and makes building editor plugins, terminal tools, dashboards, and automation dramatically easier.
I’m already using my terminal package browser daily, and it saves me from constantly switching to the browser while working in Neovim.
If you’re building developer tooling for Go, this API is definitely worth exploring.
Thanks to the Go team for making it available.




