Ghostty Custom Shaders Need a Full Relaunch¶
Problem¶
Editing a custom-shader GLSL file and reloading the Ghostty config with Cmd+Shift+,
appears to do nothing. The old shader keeps rendering, so successive rounds of tuning all look
identical and the effect seems broken rather than unchanged.
This wastes a lot of time, because every symptom points at the shader. The config reloads cleanly,
ghostty +validate-config stays silent, the path still resolves, and the file on disk is
demonstrably different — yet the picture never changes.
Root Cause¶
Ghostty compiles custom shaders once when the renderer builds its pipeline. Config reload compares config values, and editing the contents of a file the config already points at leaves that value untouched, so nothing triggers a recompile. Ghostty does not watch shader files for changes.
Two separate limitations compound this, both tracked upstream:
- Shader state is not fully reset on reload (discussion #10146)
- Even changing the
custom-shadervalue only affects new windows, tabs, and splits, never existing surfaces (discussion #4016)
Solution¶
Quit Ghostty entirely (Cmd+Q) and relaunch. A config reload is not enough for any shader change.
Quitting is safe for tmux work: the tmux server is parented to the init process, not to the
terminal, so quitting kills only the client and detaches the session. tmux attach restores
everything, including a running Claude Code session inside a pane. Only processes running in a
Ghostty window outside tmux are lost.
Key Learnings¶
- Verify a shader change is actually live before drawing conclusions from what it looks like. Set a parameter to an absurd value first — if the picture does not change, the pipeline is stale and no amount of tuning matters.
- Compile-check GLSL out of band rather than relying on the terminal to report failures. Ghostty
swallows shader compile errors into the render thread's log, so they never surface as config
errors. Concatenating Ghostty's uniform block with the shader body and running it through
glslc -fshader-stage=fragmentcatches syntax and type errors in a second. - Ghostty resolves
custom-shaderrelative paths against the config file's realpath, whileconfig-fileresolves against the symlink's directory. A shader stored in this repo therefore resolves through the symlink back into the repo, which works on any machine and any clone location.