Skip to content

TTY detection foreground/background color #65058

Open

Description

@jdmarshall

What is the problem this feature will solve?

For tty’s if you output any text in black, particularly when doing TUI’s one is likely to get a rude awakening when they discover that their users are using dark mode and none of that text is visible because it’s jet black on a charcoal gray background. It would be best in such cases to simply print this text in the default foreground color, but that does not guarantee that other colors will be high contrast. For instance dark blue on charcoal gray, or yellow text on iTerm's default eggshell white background, versus orange which shows well on both light and dark mode terminals.

What is the feature you are proposing to solve the problem?

Add a function to write stream to query the foreground color the way color depth can be queried. And if at all possible, also the background color.

What alternatives have you considered?

Workarounds include:

  • setting a background color and printing over it, but that makes the text/graphic look more important than it is
  • resetting the tty codes rather than setting “black” - but this fails if you are looking for a more general case of high contrast colors, like dark gray on a bright background and light gray on a dark one.

Activity

  1. nirupam-06 commented on Aug 6, 2026

    @nirupam-06

    Hi! I'm interested in working on this issue. Could you please assign it to me? Thanks!

  2. changed the title [-]TTY detection foreground color[/-] [+]TTY detection foreground/background color[/+] on Aug 6, 2026
  3. jdmarshall commented on Aug 6, 2026

    @jdmarshall
    Author

    For the spot where this problem is the worst, I've changed from styleText('black', ...) to styleText('reset', ...) but for instance on bench-node, this wouldn't suffice. One of my PRs on that project changed some text from yellow to orange so that it was legible on iTerm.

    But I recall that one of the first things I used to do on a fresh Linux install was tweak the ansi color for dark blue in the system settings because the amount of effort it took to read it in the colored output of ls was enough to break my flow when working on other things. I could read it, but it took a full beat and some squinting to make it out, especially when there was an issue of having directories of files with similar names.

  4. jdmarshall commented on Aug 6, 2026

    @jdmarshall
    Author

    @nirupam-06 There is a terminal escape code 11 which appears to have the information you're after. That's as far as I got because it would need some fallback on Windows and I escaped that ecosystem so long ago that I would be useless on that part of the effort.

  5. nirupam-06 commented on Aug 7, 2026

    @nirupam-06

    Thanks for the pointer! I'll investigate OSC 11 and see how it's supported across different terminals, including possible fallbacks for Windows. I'll report back with what I find before putting together a solution.

  6. nirupam-06 commented on Aug 7, 2026

    @nirupam-06

    Thanks for the pointer — did some research before jumping into code.

    OSC 11 (\e]11;?) is a real, widely-used mechanism (vim, neovim, tmux use it), but has two failure modes worth designing around: (1) Windows Terminal/Warp have an open bug where an unconsumed OSC 11 response leaks into the input buffer, and (2) tmux doesn't answer the query at all, so anything without a timeout will hang. Node's current tty.js color detection is sync/env-based, so this doesn't fit that model directly.

    Proposing a new opt-in async API (e.g. writeStream.getBackgroundColor() returning a Promise, best-effort, with a timeout and guaranteed full consumption of the response). Going to open a draft PR so we can hash out the design against real code rather than guessing further in the abstract — will link it here.

  7. nirupam-06 commented on Aug 8, 2026

    @nirupam-06

    Opened a draft PR with initial scaffolding: #65111

    It currently stubs out the proposed writeStream.getBackgroundColor() API (doc + function shape + placeholder test) but doesn't yet implement the actual OSC 11 query/response logic — working through the timeout handling and the response-consumption safeguards next (to avoid the leak-into-stdin issue seen in Windows Terminal/Warp). Will update here as it progresses.

  8. jdmarshall commented on Aug 8, 2026

    @jdmarshall
    Author

    Oh that tmux problem is a good catch but also hurts. Why tmux why?

  9. jdmarshall commented on Aug 8, 2026

    @jdmarshall
    Author
  10. nirupam-06 commented on Aug 9, 2026

    @nirupam-06

    Thanks for digging that up — that's genuinely useful context, and not just "tmux is annoying." Looks like tmux fires its own unconditional OSC 10/11 probes at startup, and over SSH the response can arrive after tmux's own probe window closes, so it leaks into the shell as literal text same class of bug as the Windows Terminal/Warp leak we're already guarding against, just at the tmux layer. Doesn't change the design, honestly reinforces it: timeout + full response consumption + treating undefined as a totally normal outcome (not just for genuine non-response, but for "arrived too late to matter" cases like this). No fix needed on our end beyond what we've already got planned.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature requestIssues requesting new Node.js features.

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions