Building the pkg.go.dev TUI explorer

5 min read Original article ↗

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.

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:

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

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:

The 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.

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.

There 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 definitions

  • one 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.

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.

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.

The entry point is pleasantly small.

After creating the generated API client, Bubble Tea takes over.

Most of the complexity ends up living in the update loop rather than in main.go, which is exactly where it belongs.

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.

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.