Skip to content

config: the shell and libghostty may resolve different config files #764

Description

@deblasis

Observed while measuring pane chrome with a scratch config on 2026-08-26, not
yet diagnosed. Filing with the evidence rather than a mechanism.

What was seen

The app was launched with XDG_CONFIG_HOME pointing at a scratch directory
holding a config with background, foreground, cursor-color and
vertical-tabs set.

  • background and foreground applied. Both are read from the native handle
    via ghostty_config_get.
  • cursor-color and vertical-tabs did not. Both are read on the C# side,
    through ConfigService.GetThemeValue / GetFileValue, which serve out of
    _configFileCache and _activeThemeFileCache.

vertical-tabs not applying meant vertical-tab mode could not be entered in
the harness at all, so it blocks visual verification of anything in that
layout. The Ctrl+Shift+, runtime toggle also did not fire under synthetic
input, which may or may not be the same problem.

Why it matters beyond the harness

If libghostty and the C# side can resolve different config files, the terminal
renders from one file and the chrome resolves its colours from another. That
is the same class of defect as the config-file include gap fixed by
ghostty_config_theme_is_builtin, but reached through the path rather than
through the contents.

It also means every screenshot harness under windows/scripts/ that isolates
itself with XDG_CONFIG_HOME is only half isolated: the terminal honours the
scratch config while the shell may be reading the real one. Any measurement
those harnesses produced about chrome colour should be re-checked once this is
understood, including the zero-config versus themed comparison in the pull
request that introduced the built-in theme pair.

Where to start

ConfigFilePath comes from ghostty_config_open_path -> edit.openPath ->
configPath -> file_load.preferredXdgPath, which returns the first
candidate that EXISTS, newest name first. Config.loadDefaultFiles instead
loads all three candidates in oldest-first order and merges them. Those two
resolutions can pick different files whenever more than one exists, and they
answer different questions ("which one file would I edit" versus "what did I
actually load"). Worth checking whether that is the divergence here, and
whether edit.openPath creating a missing file changes which candidate
"exists" by the time the C# side reads it.

Note the C# side has no way to ask what libghostty actually loaded. If the
answer is that it should stop guessing from a path, that is the same shape as
the fix already applied for the theme question.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions