speakeasy-api / speakeasy-api/openapi

openapi CLI stalls 5 s and emits a terminal colour query on every run when nothing answers OSC 11 (bubbletea v1 init-time probe)

Open
#250 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
276
Forks
18
Avg merge
3d 16h
Merged PRs (30d)
2

Description

Summary

Every invocation of the openapi binary, including openapi --version, writes an OSC 11 background-colour query and a cursor-position request (ESC ] 11 ; ? ESC \ then ESC [ 6 n) to the terminal before doing anything else, then waits up to 5 s for a reply. In an interactive terminal the reply arrives immediately and is consumed. Under anything that hands the CLI a pseudo-terminal without relaying the reply, which is how pre-commit runners such as lefthook run hooks, the CLI blocks for the full timeout and the escape sequences land in the hook's captured output. When the real terminal does answer, the CLI never consumes the reply and it shows up as junk like 11;rgb:2424/2424/2424;1R in the shell.

This is not the CLI's own code. cmd/openapi/go.mod requires github.com/charmbracelet/bubbletea v1.3.10, and bubbletea v1's tea_init.go calls lipgloss.HasDarkBackground() from a package init(), so the query fires for any binary that links bubbletea, TUI or not. termenv's OSCTimeout is a hard-coded 5 s. Upstream tracked this as charmbracelet/bubbletea#1771 and closed it as not planned because v2 no longer queries at init.

Reproduction

macOS, TERM=xterm-256color, openapi built with go install github.com/speakeasy-api/openapi/cmd/openapi@latest (v0.0.0-20260826005500-83ebf39fa45e). script -q /dev/null ... gives the process a pty that nothing answers.

$ printf 'openapi: 3.1.0\ninfo:\n  title: t\n  version: "1"\npaths: {}\n' > spec.yaml

$ /usr/bin/time -p script -q /dev/null openapi spec lint spec.yaml < /dev/null | cat -v | head -1
^[]11;?^[\^[[6nLinting OpenAPI document: spec.yaml^M
real 5.02

$ CI=1 /usr/bin/time -p script -q /dev/null openapi spec lint spec.yaml < /dev/null | cat -v | head -1
Linting OpenAPI document: spec.yaml^M
real 0.02

$ /usr/bin/time -p script -q /dev/null openapi --version < /dev/null | cat -v
^[]11;?^[\^[[6nv0.0.0-20260826005500-83ebf39fa45e
real 5.02

CI=1 helps because termenv's isTTY() returns false whenever CI is set, which skips the query. From a lefthook pre-commit hook on the same machine I measured about 5.8 s with the reply leaking into the output, and 0.4 s with CI=1.

Expected

openapi spec lint and openapi --version don't touch the terminal or pay a timeout unless a TUI is actually about to start.

Suggested fix

The query runs at package init, before main(), so the CLI can't gate it on "is this really an interactive TTY" from its own code, and setting CI from inside the binary is too late as well. The options I see:

  1. Move to bubbletea v2 (with the matching lipgloss/huh releases). v2 doesn't query at init, which is why upstream closed #1771.
  2. Until then, document CI=1 as the escape hatch for pre-commit hooks and other non-interactive runs, since termenv already honours it.

Happy to send a PR for either once you say which way you'd like to go.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with cmd/openapi/go.mod and inspect bubbletea v1's tea_init.go, especially its init-time lipgloss.HasDarkBackground() call. Confirm the behavior with the script-based reproduction for openapi spec lint and openapi --version. Done means non-TUI invocations neither emit terminal queries nor wait 5 seconds, with the accepted approach—dependency migration or CI documentation—clearly recorded.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.