The host validation code previously expected IPv6 addresses to be
enclosed in [brackets], but that's not how ssh(1) expects them.
This change removes that requirement and reimplements the host
validation routine to check for valid hostnames and IP addresses (IPv4
and IPv6) using standard routines rather than custom logic.
Fixes#9251
std.net.isValidHostname is currently too generous. It considers strings
like ".example.com", "exa..mple.com", and "-example.com" to be valid
hostnames, which is incorrect according to RFC 1123 (the currently
accepted standard).
Until the standard library function is improved, we can use this local
implementation that does follow the RFC 1123 standard.
I asked Claude to perform an audit of the code based on its understand
of the RFC. It suggested some additional test cases and considers the
overall implementation to be robust (its words) and standards compliant.
Ref: https://www.rfc-editor.org/rfc/rfc1123
`fish_add_path` by default updates the `fish_user_paths` universal
variable which makes the modification persist across shell sessions.
The integration also tries to update the `fish_user_paths` when the
desired path already appears in the `PATH` environment variable but not
in `fish_user_paths`. Because `fish_user_paths` will always be inserted
before the inherited `PATH` env. This makes the added path
unintentionally has a higher priority.
This patch fixes the above issues by adding `--global` and `--path`
options to `fish_user_paths` which limits the modification scope and
ensures that the path won't be added if it already exists in `PATH`.
Ref: https://fishshell.com/docs/current/cmds/fish_add_path.html
Fixes#2731 (again)
This regressed in 1.2 due to the renderer rework missing porting this. I
believe this issue is still valid even with the rework since the font
grid changes the atlas and if there are still cached cells that
reference the old atlas coordinates it will produce garbage.
Fixes#9191
This changes our color change operations from writing to the renderer
mailbox directly to using our `rendererMailboxWriter` function which
handles the scenario where the mailbox is full by yielding the lock,
waking up the renderer, and retrying later.
This is a known deadlock scenario we've worked around since the private
beta days, but unfortunately this slipped through and I didn't catch it
in review.
What happens here is it's possible with certain escape sequences for the
IO thread to saturate other mailboxes with messages while holding the
terminal state lock. This can happen to any thread. This ultimately
leads to starvation and all threads deadlock.
Our IO thread is the only thread that produces this kind of massive
stream of events while holding the lock, so we have helpers in it to
attempt to queue (cheap, fast) and if that fails then to yield the lock,
wakeup the target thread, requeue, and grab the lock again (expensive,
slow).
This hasn't caused any known bugs but leads to selection memory
corruption and assertion failures in runtime safe modes. When the
terminal screen changes (primary to secondary) and we have an active
dragging mode going either by moving the mouse or our selection tick
timer, we should halt.
We still keep the mouse state active which lets selection continue once
the screen switches back.
This might fix#9191, but since I don't have a reproduction I can't be
sure. In any case, this is a bad bug that should be fixed.
The issue is that we weren't checking our scroll timer completion state.
This meant that if `start_scroll_timer` was called multiple times within
a single loop tick, we'd enqueue our completion multiple times, leading
to various undefined behaviors.
If we don't enqueue anything else in the interim, this is safe by
chance. But if we enqueue something else, then we'd hit a queue
assertion failure and honestly I'm not totally sure what would happen.
I wasn't able to trigger the "bad" case, but I was able to trigger the
benign case very easily. Our other timers such as the renderer cursor
timer already have this protection.
Let's fix this and continue looking...
As pointed out in #9156, an unintended consequence of all the work to
get icon sizing right is that `adjust-icon-height` now only applies to
the small icons you get when the next cell is not whitespace. Large
icons are unaffected.
With this PR, `adjust-icon-height` affects the maximum height of every
symbol specifying the `.icon` constraint height, regardless of
constraint width. This includes most Nerd Font icons, but excludes emoji
and other unicode symbols, and also excludes terminal graphics-oriented
Nerd Font symbols such as Powerline symbols.
In the following screenshots, **Baseline** is without
`adjust-icon-height`, while **Before** and **After** are with
`adjust-icon-height = -25%`.
**Baseline**
<img width="711" height="95" alt="Screenshot 2025-10-11 at 23 28 20"
src="https://github.com/user-attachments/assets/7499db4d-75a4-4dbd-b107-8cb5849e31a3"
/>
**Before** (only small icons affected)
<img width="711" height="95" alt="Screenshot 2025-10-11 at 23 20 12"
src="https://github.com/user-attachments/assets/9afd9fbf-ef25-44cc-9d8e-c39a69875163"
/>
**After** (both small and large icons affected, but not emoji)
<img width="711" height="95" alt="Screenshot 2025-10-11 at 23 21 05"
src="https://github.com/user-attachments/assets/90999f59-3b43-4684-9c8e-2c3c1edd6d18"
/>
Previously, the fish shell integration interfered with fish's builtin vi
mode cursor switching configurations such as `$fish_cursor_default` and
`$fish_cursor_insert`.
```console
$ ghostty --config-default-files=false -e fish --no-config --init-command 'source "$GHOSTTY_RESOURCES_DIR"/shell-integration/fish/vendor_conf.d/ghostty-shell-integration.fish; fish_vi_key_bindings'
```
The above command starts fish in vi mode with Ghostty shell
integrations. Manually loading the integration is necessary due to
`--no-config` blocking auto injection.
1. At the prompt, fish is in insert mode, and the cursor is a blinking
beam. However, press escape and then "i" to exit then re-enter insert
mode, and the cursor will be a solid beam due to the
`$fish_cursor_unknown` setting. Without the shell integration, insert
mode always uses a solid beam cursor.
2. A similar problem shows if we start fish with `fish_vi_key_bindings
default`. The cursor ends up as a blinking beam in normal mode only due
to the shell integration interfering. This glitch can also be reset away
by entering then exiting insert mode.
3. Also, `$fish_cursor_external` has no effect when used with shell
integration. After `fish_vi_key_bindings`, set it to `line`, run cat(1),
and shell integration will give you a blinking block, not the asked for
line/beam.
I verified that this patch makes the shell integration stop interfering
in three scenarios above, and it still changes the cursor when not using
fish's vi mode.
Note that `$fish_cursor_*` variables can be set when fish isn't in vi
mode, so they're not great signals for the shell integration hooks.
Of course #9142 would require a minor follow-up!
* Scale groups can cut across patch sets, but not across fonts. We had
some scale group mixing between Font Awesome and the weather symbols,
which is removed by this PR.[^cp_table_full]
* There's one case where a scale group includes a glyph that's not part
of any patch sets, just for padding out the group bounding box.
Previously, an unrelated glyph from a different font would be pulled in.
Now we use an appropriate stand-in. (See code comment for details.)
* I noticed overlaps weren't being split between each side of the
bounding box, they were added to both sides, resulting in twice as much
padding as specified.
Screenshots showing the extra vertical padding for progress bar elements
due to the second bullet point:
**Before**
<img width="191" height="42" alt="Screenshot 2025-10-11 at 15 33 54"
src="https://github.com/user-attachments/assets/cf288cce-86d3-46fd-ae86-18e5c274b0e4"
/>
**After**
<img width="191" height="42" alt="Screenshot 2025-10-11 at 15 33 20"
src="https://github.com/user-attachments/assets/7ac799c7-bf50-4e65-a74a-f8a2c42d2441"
/>
[^cp_table_full]: Forming and using the merged `cp_table_full` table
should have been a red flag. Such a table doesn't make sense, it would
be a one-to-many map. You need the names of the original fonts to
disambiguate.
Fixes#9076
**Before**
<img width="128" height="57" alt="Screenshot 2025-10-11 at 00 07 09"
src="https://github.com/user-attachments/assets/a6b416d5-dae1-4cea-a836-00640ceaf39b"
/>
**After**
<img width="128" height="57" alt="Screenshot 2025-10-11 at 00 07 31"
src="https://github.com/user-attachments/assets/7d2df7b1-4767-4e2d-84d2-8301da5c6602"
/>
These screenshots show the chevrons mentioned in
https://github.com/ghostty-org/ghostty/discussions/7820#discussioncomment-14617170,
which should be scaled as a group but were not until this PR.
The added code downloads each individual symbol font file from the Nerd
Fonts github repo (making sure to get the version corresponding to the
vendored `font-patcher.py`) and iterates over all of them to build the
correct and complete codepoint mapping table. The table is saved to
`nerd_font_codepoint_tables.py`, which `nerd_font_codegen.py` will reuse
if possible instead of downloading the font files again.
I'm not going to utter any famous last words or anything, but... after
this, I don't think the number of remaining issues with icon
scaling/alignment is _large._
Previous PR: #8535 (merged but problem persists)
Issues: #5934
The Ghostty window will always start with the title "Ghostty" at
startup, and then immediately change to the correct window title. This
is a problem when using compositors like Hyprland and Niri if you want
to create rules for floating windows and similar, as the window title
isn't detected at startup.
This fixes the bad behaviour both for title configured in the config
file, and for processes started with the --title argument.
In this fix I've updated the `tags.zig` `closureComputedTitle()`
function to get the title from the passed in config, and use that as a
fallback before the default `Ghostty` fallback.
Previous behaviour as logged by `niri msg event-stream`:
> Window opened or changed: Window { id: 19, title: Some("Ghostty"),
app_id: Some("com.mitchellh.ghostty-debug"), pid: Some(802495),
workspace_id: Some(1), is_focused: true, is_floating: false, is_urgent:
false, layout: WindowLayout { pos_in_scrolling_layout: Some((3, 1)),
tile_size: (2266.0, 1365.0), window_size: (2266, 1365),
tile_pos_in_workspace_view: None, window_offset_in_tile: (0.0, 0.0) } }
Window layouts changed: [(6, WindowLayout { pos_in_scrolling_layout:
Some((4, 1)), tile_size: (2266.0, 1365.0), window_size: (2266, 1365),
tile_pos_in_workspace_view: None, window_offset_in_tile: (0.0, 0.0) })]
Window opened or changed: Window { id: 19, title:
Some("pr-test-title-fix"), app_id: Some("com.mitchellh.ghostty-debug"),
pid: Some(802495), workspace_id: Some(1), is_focused: true, is_floating:
false, is_urgent: false, layout: WindowLayout { pos_in_scrolling_layout:
Some((3, 1)), tile_size: (2266.0, 1365.0), window_size: (2266, 1365),
tile_pos_in_workspace_view: None, window_offset_in_tile: (0.0, 0.0) } }
New behaviour:
> Window opened or changed: Window { id: 20, title:
Some("pr-test-title-fix"), app_id: Some("com.mitchellh.ghostty-debug"),
pid: Some(804534), workspace_id: Some(1), is_focused: true, is_floating:
false, is_urgent: false, layout: WindowLayout { pos_in_scrolling_layout:
Some((3, 1)), tile_size: (2266.0, 1365.0), window_size: (2266, 1365),
tile_pos_in_workspace_view: None, window_offset_in_tile: (0.0, 0.0) } }
Window layouts changed: [(6, WindowLayout { pos_in_scrolling_layout:
Some((4, 1)), tile_size: (2266.0, 1365.0), window_size: (2266, 1365),
tile_pos_in_workspace_view: None, window_offset_in_tile: (0.0, 0.0) })]
This fixes the problem as shown in the output. I have only tested this
on Linux (Arch with Niri).
Sorry, I'm living dangerously here and haven't started a discussion.
New ghostty user. When working interactively with SQL clients you're
often writing semi-colons at the end of statements, e.g. `select * from
table;`
It's super annoying when you double-click to select the word `table` it
actually selects `table;` Anecdotally, this behaviour disagrees with
other terminals I've tried (tho not exhaustive).
Disclosure: Claude wrote this code but, ironically, I "assisted it" by
pointing to the file and function after uncovering issue #30 and
relevant PR.
As promised in #8990.
I opted for hardcoded metrics and bounding boxes rather than actually
loading fonts and glyphs, both to avoid backend dependence and limit the
focus to the constraint calculations themselves, and because I wanted to
test a case that isn't exhibited by any of the fonts available in the
repo.
This also fixes an error from #8990, probably due to a botched
cherry-pick or rebase.
Since #8999, `macos-custom-icon` works when its a fully expanded
absolute path like `/Users/username/dir/icon.icns`, but not when it's
abbreviated as `~/dir/icon.icns`. Users were understandably surprised
and confused by this. This PR adds tilde expansion using `NSString`s
built-in property for this.
Also removed a line from the config docs that seemed erroneous. Given
that the option has a functional default, it seems incorrect to say that
it's required.
You can pretty simply reproduce a crash on `main` in `Debug` mode by
running `printf "مرحبًا \n"` with your primary font set to one that
supports Arabic such as Cascadia Code/Mono or Kawkab Mono, which will
cause CoreText to output the shaped glyphs non-monotonically which hits
the assert we have in the renderer.
In `ReleaseFast` this assert is skipped and because we already moved
ahead to the space glyph (which belongs at the end but is emitted first)
all of the glyphs up to that point are lost. I believe this is probably
the cause of #8280, I tested and this change seems to fix it at least.
Included in this PR is a little optimization: we were allocating buffers
to copy glyphs etc. from runs to every time, even though CoreText
provides `CTRunGet*Ptr` functions which get *pointers* to the internal
storage of these values- these aren't guaranteed to return a usable
pointer but in that case we can always fall back to allocating again.
Also avoided allocation while processing glyphs by ensuring capacity
beforehand immediately after creating the `CTLine`.
The performance impact of this PR is negligible on my machine and
actually seems to be positive, probably due to avoiding allocations if I
had to guess.
Signal handlers are connected to surface objects in two spots - when a
tab is added to a page and when the split tree changes. This resulted in
duplicate signal handlers being added for each surface. This was most
noticeable when copying the selection to the clipboard - you would see
two "Copied to clipboard" toasts. Ensure that there is only one signal
handler by removing any old ones before adding the new ones.
regressed in the handling of the Powerline glyphs themselves by letting
them get caught in an early exit that imposes a constraint width of 1.
This PR fixes the regression and adds corresponding tests. Tried to be
somewhat principled about why the special treatment is warranted, hence
the new helper function `isGraphicsElement`.
**Before**
<img width="270" height="44" alt="Screenshot 2025-10-02 at 00 16 54"
src="https://github.com/user-attachments/assets/9e975434-114c-44d5-a4ed-ac6a954b9d00"
/>
**After**
<img width="270" height="44" alt="Screenshot 2025-10-02 at 00 16 11"
src="https://github.com/user-attachments/assets/20545e74-c9f9-4a6b-9bf0-a7cf1d38c3a0"
/>
Follow-up to #8563, which broke scaling without alignment. This change
recovers the behavior from before #8563, such that a scaled group is
clamped to the constraint width and height if necessary, and otherwise,
scaling does not shift the center of the group bounding box.
As a part of this change, horizontal alignment was rewritten to assume
the face is flush with the left edge of the cell. The cell-to-face
offset in the rendering code is then applied regardless of the value of
`align_horizontal`. This both simplifies the code and improves
consistency, as it ensures that the offset is the same for all
non-bitmap glyphs (rounded in FreeType, not rounded in CoreText). It's
the right thing to do following the align-to-face changes in #8563.
Some bell features should be triggered on the receipt of every BEL
character, namely `audio` and `system`. However, Ghostty was setting a
boolean to `true` upon the receipt of the first BEL. Subsequent BEL
characters would be ignored until that boolean was reset to `false`,
usually by keyboard/mouse activity.
This PR fixes the problem by ensuring that the `audio` and `system`
features are triggered every time a BEL is received. Other features
continue to be triggered only when the `bell-ringing` boolean state
changes.
Fixes#8957
I used the new CPU counter mode in Instruments.app to track down
functions that had instruction delivery bottlenecks (indicating i-cache
misses) and picked a bunch of trivial functions to mark as inline (plus
a couple that are only used once or twice and which benefit from
inlining).
The size of `macos-arm64/libghostty-fat.a` built with `zig build
-Doptimize=ReleaseFast -Dxcframework-target=native` goes from
`145,538,856` bytes on `main` to `145,595,952` on this branch, a
negligible increase.
These changes resulted in some pretty sizable improvements in vtebench
results on my machine (Apple M3 Max):
<img width="983" height="696" alt="image"
src="https://github.com/user-attachments/assets/cac595ca-7616-48ed-983c-208c2ca2023f"
/>
With this, the only vtebench test we're slower than Alacritty in (on my
machine, at 130x51 window size) is `dense_cells` (which, IMO, is so
artificial that optimizing for it might actually negatively impact real
world performance).
I also did a pretty simple improvement to how we copy the screen in the
renderer, gave it its own page pool for less memory churn. Further
optimization in that area should be explored since in some scenarios it
seems like as much as 35% of the time on the `io-reader` thread is spent
waiting for the lock.
> [!NOTE]
> Before this is merged, someone really ought to test this on an x86
processor to see how the performance compares there, since this *is*
tuning for my processor specifically, and I know that M chips have
pretty big i-cache compared to some x86 processors which could impact
the performance characteristics of these changes.
This is my final set of fixes to the font patcher/icon scaling code. It
builds on #8563 and there's not much reason to pay attention here until
that one has been reviewed (the unique changes in this PR only touch the
two `nerd_font_*` files; the other 8 files in the diff are just #8563).
However, I wanted to make sure the full set of changes/fixes I propose
are out in the open, such that any substantial edits by maintainers
(like in #7953) can take into account the full context.
I think this and the related patches should be considered fixes, not
features, so I hope they can be considered for a 1.2.x release.
This PR fixes some bugs in the extraction of scale and alignment rules
from the `font_patcher` script. Roughly in order of importance:
* Nerd fonts apply an offset to some codepoint ranges when extracting
glyphs from their original font (e.g., Font Awesome) and placing them in
a Nerd Font. Rules are specified in terms of the former codepoints, but
must be applied to the latter. This offset was previously not taken into
account, so rules were applied to the wrong glyphs, and some glyphs that
should have rules didn't get any.
* Previously, the rules from every single patch set was included, but
the embedded Symbols Only font doesn't contain all of them. Most
importantly, there's a legacy patch set that only exists for historical
reasons and is never used anymore, which was overwriting some other
rules because of overlapping codepoint ranges. Also, the Symbols Only
font contains no box drawing characters, so those rules should not be
included. With this PR, irrelevant patch sets are filtered out.
* Some patch sets specify overlapping codepoint ranges, though in
reality the original fonts don't actually cover the full ranges and the
overlaps just imply that they're filling each other's gaps. During font
patching, the presence/absence of a glyph at each codepoint in the
original font takes care of the ambiguity. Since we don't have that
information, we need to hardcode which patch set "wins" for each case
(it's not always the latest set in the list). Luckily, there are only
two cases.
* Many glyphs belong to scale groups that should be scaled and aligned
as a unit. However, in `font_patcher`, the scale group is _not_ used for
_horizontal_ alignment, _unless_ the entire scale group has a single
advance width (remember, the original symbol fonts are not monospace).
This PR implements this rule by only setting `relative_width` and
`relative_x` if the group is monospace.
There are some additional tweaks to ensure that each codepoint actually
gets the rule it's supposed to when it belongs to multiple scale groups
or patch sets, and to avoid setting rules for codepoints that don't
exist in the embedded font.
In CoreText, when thickening (font smoothing) is enabled or Ghostty is
synthesizing a bold face, the glyph bounding box is padded to make sure
the thicker glyph can fit. Currently, this happens before applying
constraints (scaling and alignment), which makes the size and position
of constrained glyphs dependent on font size, font thickening strength,
and display DPI.
With this PR, constraints are applied before any other adjustments, and
padding is applied directly to the rasterization canvas without
modifying any metrics.
For consistency, I also moved constraint application above emboldening
in the FreeType code, although under that API, the two operations are
orthogonal as far as I can tell.
Secondly, this PR moves glyph centering above bitmap quantization, as
centering is generally fractional and will therefore undo the quantizing
if done after.
Supersedes #8552.
Fixes#8944
When we drag the only tab out of the tab overview, this triggers an
`n-pages` signal with 0 pages. If we close the window in this state, it
causes both Ghostty to exit AND the drag/drop to fail. Even if we
pre-empt Ghostty exiting by modifying the application class, the
drag/drop still fails and the application leaks memory and enters a bad
state.
The solution is to keep the window open if we go to `n-pages == 0` and
we have the tab overview open.
Interestingly, if you click to close the final tab from the tab
overview, Adwaita closes the tab overview so it still triggers the
window closing behavior (this is good, this is desired).
Fixes https://github.com/ghostty-org/ghostty/discussions/8697 by making
`OK` the suggested default and activating it by default.
Previously `OK` was `destructive` which imo is not a good approach for
just setting a terminal title.
Resolves Issue: #8670
Now precision and discrete scrolling can be scaled independently.
Supports following configuration,
```code
# Apply everywhere
mouse-scroll-multiplier = 3
# Apply separately
mouse-scroll-multiplier = precision:0.1,discrete:3 (default)
# Also it's order agnostic
mouse-scroll-multiplier = discrete:3,precision:2
# Apply one, default other
mouse-scroll-multiplier = precision:2
```
The default precision value is set 0.1, as it felt natural to me at
least on my track-pad. I've also set the min clamp value precision to
0.1 as 0.01 felt kind of useless to me but I'm unsure.
This is nicer because it only sets the filetype if it hasn't already
been set. :setf[iletype] has been available since vim version 6.
See: https://vimhelp.org/options.txt.html#%3Asetf
Resolves#8890
If you try to create the config file when the directory already exists,
you (I) get an error that the _file_ path already exists.
```
warning(config): error creating template config file err=error.PathAlreadyExists
```
Even though the file does not exist. By changing the API entry point,
this error goes away.
I have no solid explanation for why this change works.
| State | Old Behavior | New Behavior |
|--------|--------|--------|
| A config file exists | N/A | N/A |
| No config file, no directory | create directory and config file | N/A
|
| No config file, yes directory | fail to create on config file | create
config file |
This behavior is confirmed on my macOS 26 machine. It is the least
intrusive change I could make, and in all other situations should be a
no-op.
Fix provided by @jcollie
The swift `open_config` action was triggering an allocation error
`error(gpa): Allocation size 41 bytes does not match free size 40.`.
> A string that was created as a `[:0]const u8` was cast to `[]const u8`
and then freed. The sentinel is the off-by-one.
@jcollie
For full context, see
https://discord.com/channels/1005603569187160125/1420367156071239820
Co-authored-by: Jeffrey C. Ollie <jcollie@dmacc.edu>
Fixes#8849
Previously, the `parseAutoStruct` function that was used to parse
generic structs for the config simply split the input value on commas
without taking into account quoting or escapes. This led to problems
because it was impossible to include a comma in the value of config
entries that were parsed by `parseAutoStruct`. This is particularly
problematic because `ghostty +show-config --default` would produce
output like the following:
```
command-palette-entry = title:Focus Split: Next,description:Focus the next split, if any.,action:goto_split:next
```
Because the `description` contains a comma, Ghostty is unable to parse
this correctly. The value would be split into four parts:
```
title:Focus Split: Next
description:Focus the next split
if any.
action:goto_split:next
```
Instead of three parts:
```
title:Focus Split: Next
description:Focus the next split, if any.
action:goto_split:next
```
Because `parseAutoStruct` simply looked for commas to split on, no
amount of quoting or escaping would allow that to be parsed correctly.
This is fixed by (1) introducing a parser that will split the input to
`parseAutoStruct` into fields while taking into account quotes and
escaping. And (2) changing the `ghostty +show-config` output to put the
values in `command-palette-entry` into quotes so that Ghostty can parse
it's own output.
`parseAutoStruct` will also now parse double quoted values as a Zig
string literal. This makes it easier to embed control codes, whitespace,
and commas in values.
Replaces #8786
The author of the original PR used AI agents to create that PR. To the
extent that this PR borrows code from that PR (mostly in the tests) AI
was used in the creation of this PR.
Powerline glyphs were treated as whitespace, giving the preceding cell a
constraint width of 2 and cutting off icons in people's prompts and
statuslines. It is however correct to not treat Powerline glyphs like
other Nerd Font symbols; they should simply be treated as normal
characters, just like their relatives in the block elements unicode
block.
This resolves
https://discord.com/channels/1005603569187160125/1417236683266592798
(never promoted to an issue, but real and easy to reproduce).
**Tip**
<img width="215" height="63" alt="Screenshot 2025-09-21 at 16 57 58"
src="https://github.com/user-attachments/assets/81e770c5-d688-4d8e-839c-1f4288703c06"
/>
**This PR**
<img width="215" height="63" alt="Screenshot 2025-09-21 at 16 58 42"
src="https://github.com/user-attachments/assets/5d2dd770-0314-46f6-99b5-237a0933998e"
/>
The constraint width logic was untested but contains some quite subtle
interactions, so I wrote a suite of tests covering the cases I'm aware
of.
While working on this code I also resolved a TODO comment to add all the
box drawing/block element type characters to the set of codepoints
excluded from the minimum contrast settings.
This was not ported to gtk-ng before old runtime was removed, breaking
shell integration on Flatpak.
This implementation is copied verbatim from old runtime.
Avoid leaking snap environment values and in particular the `$SNAP*`
values to the children that we run from the terminal.
Do this programmatically instead of the launcher, since ghostty needs
know the environment it runs in, while it must not leak the info to the
children.
We've also another leak on snap, that creates a more visible problem
(wrong matching of children applications) that is the apparmor security
profile.
I've handled it at
cc3b46f600
but that requires some love in order to fully decouple the snap option
to the build, to avoid including it in non-snap builds, so an help would
be appreciated there.
> This PR was contains code (in `filterSnapPaths`) that was improved by
DeepSeek.