The CLI no longer depends on github.com/planetscale/planetscale-go.
As of July 2026, the Go API client that used to live in the planetscale-go
repository is vendored into this repo at internal/planetscale/ and is
maintained here. The import path is:
import ps "github.com/planetscale/cli/internal/planetscale"Every API change used to require two PRs and a release dance: change
planetscale-go, tag a release, bump go.mod here, then write the CLI
feature. The CLI was the only internal consumer of planetscale-go, and the
published OpenAPI spec covers under half of the endpoints the CLI uses
(none of the vtctld/workflow/data-import surface), so generating a client
from the spec was not an option. Copying the client in removes the
cross-repo step entirely.
- Add the endpoint to api-bb, then add the method/types directly in
internal/planetscale/in the same CLI PR. There is no SDK release to wait for and no version to bump. - Do not add
github.com/planetscale/planetscale-goback togo.mod, and do not update the planetscale-go repo as a prerequisite for CLI work. A test (TestNoPlanetscaleGoDependencyininternal/planetscale/) fails the build if the module shows up ingo.modor in any import. - Service interfaces (e.g.
DatabasesService) live next to their implementations; hand-written mocks are ininternal/mock/and must be updated when an interface changes, same as before. - The client's
User-Agentstarts withpscale-cli/<version>, set by the CLI at startup viaplanetscale.WithUserAgent(seeinternal/cmd/root.go).WithUserAgentkeeps upstream's prepend semantics so the package stays byte-identical to what the sync publishes (see below); the full header ispscale-cli/<version> planetscale-go/unknown. - Keep this package self-contained: do not import other CLI packages from
internal/planetscale/. The synced copy must build against planetscale-go's own minimalgo.mod. - Only public (
v1/...) endpoints are synced to planetscale-go. If the CLI needs an internal (non-v1) endpoint, put the whole service in a*_internal.gofile (tests in*_internal_test.go); the sync script skips those. Internal services must not be wired into theClientstruct inclient.go, since that file is synced: expose them via a method or constructor defined in the internal file itself. If a synced file accidentally references an internal symbol, the sync workflow's standalone build fails, so mistakes cannot ship silently. (d1_import_notifications.gopredates this rule: it hits an internal endpoint but is already published in planetscale-go, so it stays.)
The public planetscale-go module still exists for external users, but it is now a read-only mirror of this package. The CLI copy is the source of truth; do not make client changes in the planetscale-go repo.
The sync is the Sync client to planetscale-go workflow
(.github/workflows/sync-planetscale-go.yml), which uses
script/sync-planetscale-go.sh. It runs on CLI releases
or manually, copies internal/planetscale/ into planetscale-go (minus
doc.go, dependency_test.go, and *_internal.go files, which are
CLI-only), builds and tests
the copy standalone, and opens a PR there with a gorelease API
compatibility report. It never pushes to main: a human reviews the PR and
picks the next tag, bumping the major version if the report shows
incompatible changes. Auth comes from the CLI GitHub App (the same one
release.yml uses), which must be installed on planetscale-go.