## Summary
Adds a new environment variable `GHOSTTY_QUICK_TERMINAL=1` that is set
when a terminal surface is launched as a quick terminal. This allows
shell configurations to conditionally adjust behavior based on whether
the terminal is a quick terminal.
Closes#3985
<img width="1430" height="228" alt="CleanShot 2025-11-23 at 12 39 27
png"
src="https://github.com/user-attachments/assets/1085c19b-9d58-4603-a03d-662bfde47095"
/>
## Motivation
Quick terminals are designed as ephemeral, singleton windows for quick
commands. Many users (especially tmux users) have shell configurations
that automatically attach to or start tmux sessions on terminal launch.
This automatic behavior conflicts with the quick terminal use case.
Example from the issue:
```zsh
# Users want to skip this in quick terminals
if [[ -z "$TMUX" ]]; then
tmux attach || tmux new
fi
With this PR, users can now detect quick terminals and adjust their shell behavior:
if [[ -z "$TMUX" ]] && [[ -z "$GHOSTTY_QUICK_TERMINAL" ]]; then
tmux attach || tmux new
fi
```
## Implementation
- macOS: Added GHOSTTY_QUICK_TERMINAL=1 to SurfaceConfiguration
environment variables in QuickTerminalController.swift:345-351
- Linux/GTK: Added environment variable check in
src/apprt/gtk/class/surface.zig:1469-1472 within defaultTermioEnv()
The environment variable is automatically inherited by split surfaces.
## Note on Scripting API
I'm aware that @rhodes-b mentioned this functionality was planned for
the scripting API (issue #3985). However, I believe this simpler
environment variable approach provides immediate value for tmux users
and shell configuration use cases, while the scripting API can later
provide more comprehensive surface introspection capabilities.
## AI Assistance Disclosure
This PR was written with Claude Code assistance. The Linux/GTK
implementation was fully AI-generated. I implemented the mac version
myself after Claude Code helped me understand the codebase architecture
and locate the appropriate files.
This makes `cursorStyle` utilize `RenderState` to determine the
appropriate cursor style. This moves the cursor style logic outside the
critical area, although it was cheap to begin with.
This always removes `viewport_is_bottom` which had no practical use.
This change should give more consistent results between high and low DPI
displays, and generally approximate the authorial intent of the metrics
a little better.
Also changed the cell height adjustment to prioritize the top or bottom
when adjusting by an odd number depending on whether the face is higher
or lower in the cell than it "should" be. This should make it easier for
users who have an issue with a glyph protruding from the cell to adjust
the height and resolve it.
The code that re-creates the font descriptor from scratch using the same
attributes also rubs off the magic dust that makes CoreText not throw a
fit at us for using a "hidden" system font (name prefixed with a dot) by
name when we use the descriptor. This means that a small subset of chars
that only have glyphs in these fallback system fonts like ".CJK Symbols
Fallback HK Regular" and ".DecoType Nastaleeq Urdu UI" would not be able
to be rendered, since when we requested the font with the non-magical
descriptor CoreText would complain in the console and give us Times New
Roman instead.
Using `CTFontDescriptorCreateCopyWithAttributes` to clear the charset
attribute instead of recreating from scratch makes the copy come out
magical, and CoreText lets us instantiate the font from it, yippee!
### ℹ️ For anyone who came to this PR from a search engine rabbit hole
trying to figure this out for your own code:
It seems like if you want to use one of these fonts, you have to avoid
creating a new descriptor from scratch with the name. To create a
descriptor with one of these names that CoreText won't get upset about,
you have to get it in one of these ways (there may be others but these
are ones that definitely work at time of writing):
- Get it from `CTFontCreateForString`(`WithLanguage`) with a character
only provided by that font.
- Get it from `CTFontCreateUIFontForLanguage` or any of the mechanisms
for generally receiving a system font that you don't necessarily have
full control over the exact choice of font with.
- Get it from a collection created with
`CTFontCollectionCreateMatchingFontDescriptors`
- Get it from `CTFontCreateWithGraphicsFont` ... and it seems that for
now, `CGFontCreateWithFontName` lets you use these "hidden" names
without complaining :)
I wouldn't trust any of these methods to necessarily *continue* working
in to the future, since Apple seems to be trying to dissuade
*intentional* use of any particular named hidden system font.
Realistically, the `CreateForString` option is the most likely to stick
around.
If all else fails, check FireFox or Chrome's source code to see how
they're solving it in current year.
And to help it get indexed for those looking for it...
<details>
<summary>CoreText's angry message</summary>
```
CoreText note: Client requested name ".CJKSymbolsFallbackHK-Regular", it will get TimesNewRomanPSMT rather than the intended font. All system UI font access should be through proper APIs such as CTFontCreateUIFontForLanguage() or +[NSFont systemFontOfSize:].
CoreText note: Set a breakpoint on CTFontLogSystemFontNameRequest to debug.
```
</details>