Skip to content

Discover subcommands in k6 x - #5972

Merged
inancgumus merged 10 commits into
masterfrom
k6-x
May 18, 2026
Merged

Discover subcommands in k6 x#5972
inancgumus merged 10 commits into
masterfrom
k6-x

Conversation

@inancgumus

@inancgumus inancgumus commented May 12, 2026

Copy link
Copy Markdown
Contributor

What?

k6 x lists subcommands (baked + advertised by the registry (official and community)).

$ k6 x
...
Available Commands:
  agent       Bootstrap an AI-assisted k6 testing workflow in any editor
  docs        CLI k6 docs for AI agents and users
  explore     Explore k6 extensions for Automatic Resolution
  mcp         An MCP server for k6 for AI agents

Note

We retrieve the catalog from the network (10s timeout) and cache it.

TAB completions

$ k6 x <TAB>                # after a previous `k6 x` cached the catalog
agent  docs  explore  mcp

Tab completion lists the same set, but only when the catalog is already cached locally. Hitting <TAB> must never block on the network, so until a prior k6 x run populates the cache, completion returns only what's baked into the binary.

Why?

AI agents driving a k6 binary can't directly introspect subcommands; they're blind to extensions. As agentic workflows grow, the binary needs to answer the question "what can you do?" on its own.

Notes

All subcommands render in a single Available Commands: block. Cobra v1.4 lacks a command-group API, and tagging them by tier would require a Cobra bump or a custom help template for a marginal UX gain.

k6 x explore covers more than subcommands (all extensions), requires provisioning before it can run, and folding it into k6 would mean a stable internal API across versions, help address output mismatches with every other built-in command, and changes (+exports) inside xk6-subcommand-explore itself. A static, generated built-in extensions list was also considered a fallback and rejected: it would go stale until the next k6 release and would be out of sync.

Follow-up

  • When the k6 extension registry exposes a short field per entry, k6 x will surface it without a code change here: the catalog parser already prefers short and falls back to description.
  • --json output on the catalog endpoint for richer agent consumption.

Related

Introduces K6_PROVISION_CATALOG_CACHE_AGE so callers can tune how long the on-disk k6 extension registry catalog is treated as fresh. The knob is read by the upcoming `k6 x` registry stub renderer; declaring it first keeps the surface change isolated.
Until now the `k6 x` help only listed baked-in extension subcommands, so users had no way to discover what else the wider catalog offered. Read the on-disk catalog cache during command tree construction and register a cobra stub for every advertised subcommand not already baked in, with an annotation marking each one as registry-sourced. Invoking a stub falls through to the regular provisioning path.
The new registry stubs added in the previous commit are real cobra children, so the existing completion detector — which only fired when cobra fell back to `x` itself — silently skipped them and never triggered provisioning for stub names. Match the stub annotation explicitly so `k6 __complete x <stub> ...` provisions the extension instead of returning nothing.
With only cache-backed rendering, fresh installs and CI runs never see registry-advertised subcommands until something else seeds the cache. Fetch the catalog over HTTP on miss with a 10s timeout, write the response back to the cache, and recover the parsed subcommands for the same call. K6_PROVISION_CATALOG_URL lets tests and developers redirect the fetch; the shared test harness points it at an unreachable address so suites stay off the real registry.k6.io by default.
The first `k6 x` invocation on a fresh install pauses for up to ten seconds while the catalog downloads, with no indication anything is happening. Print a single `Loading the subcommand list...` line on stderr around the fetch and clear it afterwards on TTYs (or newline-separate it on plain pipes) so help output renders cleanly.
Cache and fetch failures previously vanished into silent swallowing, leaving users with no way to tell why `k6 x` showed an unexpectedly short list. Emit each at debug so -v surfaces them while normal stderr stays clean.
Lock in that `k6 x` lists registry-advertised subcommands when the catalog is reachable, falls back silently when it's unreachable, and stays quiet when AutoExtensionResolution is disabled. Adds an httptest helper plus a small fixture catalog reused by upcoming completion tests.
Shell completion must never hit the network: TAB feedback would freeze for ten seconds on a slow link. Lock down both directions of the gate: when the on-disk catalog cache exists, completion surfaces the stub names; when it doesn't, completion returns no stub names instead of fetching. An unreachable catalog URL stands in as the tripwire — any accidental fetch would surface as a hang.
When the cache promotes alpha to a registry stub, cobra finds it as a real child of `x` instead of falling through, so the master detection path — which only fired for unknown names — would otherwise skip provisioning. Lock in that completion under a stub still reports the extension name for the dependency check.
@inancgumus inancgumus self-assigned this May 12, 2026
@inancgumus inancgumus added the area: Auto Extension Resolution Previously known as binary provisioning. label May 12, 2026
@inancgumus
inancgumus temporarily deployed to azure-trusted-signing May 12, 2026 22:23 — with GitHub Actions Inactive
@inancgumus
inancgumus temporarily deployed to azure-trusted-signing May 12, 2026 22:25 — with GitHub Actions Inactive
szkiba
szkiba previously approved these changes May 13, 2026

@szkiba szkiba left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the solution, I just made two small (nit) comments.

Comment thread internal/cmd/x_registry.go
Comment thread cmd/state/state.go Outdated
Comment thread internal/cmd/x_registry.go Outdated
Comment thread cmd/state/state.go Outdated
K6_PROVISION_CATALOG_CACHE_AGE was non-standard. TTL is the
universally understood term for how long a cached value stays
fresh.

Co-authored-by: Iván Szkiba <szkiba@users.noreply.github.com>
@inancgumus
inancgumus requested review from oleiade and szkiba May 13, 2026 18:16
@inancgumus
inancgumus marked this pull request as ready for review May 13, 2026 18:17
@inancgumus
inancgumus requested a review from a team as a code owner May 13, 2026 18:17
@inancgumus
inancgumus temporarily deployed to azure-trusted-signing May 13, 2026 18:21 — with GitHub Actions Inactive
@inancgumus
inancgumus temporarily deployed to azure-trusted-signing May 13, 2026 18:23 — with GitHub Actions Inactive
@mstoykov
mstoykov removed the request for review from a team May 14, 2026 09:33
@inancgumus
inancgumus requested a review from mstoykov May 15, 2026 13:18
@mstoykov mstoykov added this to the v2.1.0 milestone May 15, 2026

@oleiade oleiade left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really nice 🚀 !!

@inancgumus
inancgumus merged commit 1e767c8 into master May 18, 2026
57 of 58 checks passed
@inancgumus
inancgumus deleted the k6-x branch May 18, 2026 13:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: Auto Extension Resolution Previously known as binary provisioning.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

k6 x: Fetch and show subcommands

4 participants