cursor-shaders, GLSL trails and ripples for the Ghostty and Kitty terminals
Custom cursor shaders for ghostty & kitty terminals (trails and ripple/pulse effects)
At a glance
- What is it?
- This repository collects custom cursor shaders for two terminal emulators. Ghostty gets the full set, including trail effects and cursor mode change pulses, while Kitty gets the trails only because its shader API does not expose a cursor when the trail is inactive. Every shader is a single GLSL file with its parameters and easing function at the top, so the customisation is done by editing a constant.
- Who is it for?
- Adopt this repository if you spend your day in Ghostty and want the cursor to leave a trail that makes fast terminal navigation readable, and skip it if you are on Kitty and want the mode change pulses, because the Kitty path is trails only.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 20 days ago.
- What is it written in?
- Mainly GLSL, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Two terminals, two shader models, one repository
The project provides custom cursor shaders for the Ghostty and Kitty terminals, and the first thing to understand is that the two terminals are not supported the same way. The trails work in both, with a Ghostty directory and a Kitty directory, and the file names differ between them: the Kitty ports use hyphenated names such as cursor-warp, cursor-sweep and cursor-tail where the Ghostty ones use underscores such as cursor_warp.glsl. The pulse and boom effects are Ghostty only, and the reason is a specific API limitation rather than a preference: kitty's shader API at version 0.49.2 exposes no cursor when the trail is inactive, so shape-only changes cannot trigger them. That is the kind of constraint that decides the architecture of a small project like this, and it is stated plainly rather than left for you to discover.
`cursor-warp`, `cursor-sweep`, `cursor-tail`The trail shaders, and what each one does
Three trail shaders are provided, and each is a different visual idea. The warp is described as a Neovide-like cursor trail and as the most customizable shader of the set. The sweep is an animated trail that shrinks from the previous to the current cursor position, which is a subtly different idea from a trail that persists. The tail is a comet-like trail mimicking the cursor_trail effect of the Kitty terminal, so if you are moving from Kitty to Ghostty this is the one that preserves what you had. The demos table also shows a customized entry, a faded warp combined with a ripple, which is the repository's own demonstration that the shaders compose rather than being a fixed set.
- [cursor_warp.glsl](ghostty/cursor_warp.glsl): Neovide-like cursor trail,
most customizable shader
- [cursor_sweep.glsl](ghostty/cursor_sweep.glsl): Animated trail that shrinks
from previous to current cursor position
- [cursor_tail.glsl](ghostty/cursor_tail.glsl): Comet-like trail, mimicing kitty
terminal's cursor_trail effectThe pulse effects, and the freeze you have to fix
The four pulse and boom shaders all trigger on cursor mode changes, a block cursor becoming a line cursor or the other way round, and the documentation notes that this looks cool when changing modes in vim. There is a sonic boom, an expanding filled circle, a ripple cursor, an expanding circular ring, and two rectangular variants that are the same effect with a rectangular cursor shape. The important detail is the one in the note. If you have the line cursor, which is the default, these effects will trigger and freeze on unfocus, because the cursor changes to a hollow block when the window loses focus. The solution is to add custom-shader-animation set to always in the Ghostty config. Without that line, the effect you installed will appear to hang the first time you switch applications, and the cause is not obvious.
custom-shader-animation = alwaysInstalling into Ghostty, and the config lines that matter
Installation for Ghostty is a clone into the shaders directory, and then one config line per shader in the Ghostty config file. The custom-shader key points at a file below the shaders directory, and the example shows several of them listed, with the note to replace the placeholder name with the name of any shader file such as cursor_sweep or ripple_cursor. The repository is cloned from a URL whose path differs from the repository name, which is a small detail that matters if you script the install, so it is worth copying the command rather than reconstructing it. The shaders directory in the example is the one under the Ghostty configuration directory, and the paths inside the config are relative to that directory, which is why the example writes shaders/ghostty/yourshader1.glsl rather than an absolute path.
git clone https://github.com/sahaj-b/ghostty-cursor-shaders ~/.config/ghostty/shadersInstalling into Kitty, and picking one trail
The Kitty route copies the kitty folder into the Kitty shaders directory rather than cloning the repository, because the ported files are already in the right naming scheme. The configuration then needs two lines: cursor_trail set to 1 to switch the trail on, and a custom_shaders line naming one of the three, cursor-warp, cursor-sweep or cursor-tail, with the other two shown commented out. The documentation is explicit that you pick one trail, which makes sense since the key takes a single value. The version requirement is stated in the section heading, that the trails need Kitty at least 0.49, and the note that the Kitty cursor-warp ships with the customized, faded warp values from the example, so the Kitty port is not an exact copy of the Ghostty one.
cp -r kitty/* ~/.config/kitty/shaders/Customisation is a constant at the top of the file
All the shaders have customizable parameters like colour, duration, size and thickness at the top of each file, and you adjust them there. The example shows the constants in the warp shader: a duration, a trail size, a minimum distance threshold, a blur amount, a trail thickness and a separate x thickness, plus a fade enabled flag and a fade exponent. The ripple shader has its own set, with a maximum radius, a ring thickness, a width change threshold, a colour given as a four component vector, a blur and an animation start offset. Beside the parameters there are easing functions, and the documentation explains the point of them: they control the animation curve, and you can make the effects elastic, springy, smooth or linear by changing which one is used. In trail shaders you comment and uncomment the easing functions in the code, in the pulse and boom shaders you do the same with the lines in the ANIMATION section, and you can add your own.
// in cursor_warp.glsl
const float DURATION = 0.15;
const float TRAIL_SIZE = 0.8;
const float THRESHOLD_MIN_DISTANCE = 1.0;
const float BLUR = 1.0;
const float TRAIL_THICKNESS = 1.0;Why the shaders branch instead of doing branchless math
The last section of the project documentation answers a question a shader author would ask, and the answer is a good one to have in writing. The shaders use branching with if and else rather than branchless math, because the branching here is uniform branching, which has no divergence, meaning all fragments take the same branch path, so there is no performance penalty on modern GPUs. The alternative would be worse: branchless math would force the GPU to calculate the animations every single frame, even when there is no need. That is a real trade-off and the reasoning is specific rather than generic, which is what makes it useful to a reader deciding whether to write their own effect. The inspiration for the project is credited to the Neovide cursor animations and to a Ghostty shader playground repository, and the licence is MIT.
all fragments will take the same branch path, so no performance
penalty on modern GPUsEditorial conclusion
Adopt this repository if you spend your day in Ghostty and want the cursor to leave a trail that makes fast terminal navigation readable, and skip it if you are on Kitty and want the mode change pulses, because the Kitty path is trails only. Verify three things before you wire it in: that your Kitty version is at least 0.49, since the trails need the newer shader API; that you set custom-shader-animation to always in the Ghostty config, because with the default line cursor the pulse effects trigger and then freeze when the window loses focus; and that you pick a single Kitty trail rather than several, because the configuration example shows the custom_shaders line taking one value.
Frequently asked questions
What does the cursor-shaders repository provide?
Custom cursor shaders for the Ghostty and Kitty terminals. Ghostty gets trail shaders such as cursor_warp, cursor_sweep and cursor_tail, plus pulse and boom effects that trigger on cursor mode changes, while Kitty gets the trails only in hyphenated ports such as cursor-warp, cursor-sweep and cursor-tail.
Why do the pulse and boom effects not work in Kitty?
Kitty's shader API at version 0.49.2 exposes no cursor when the trail is inactive, so shape-only changes cannot trigger those effects. The documentation also notes that the Kitty path needs Kitty 0.49 or newer and that you pick a single trail in the configuration.
How do I install the cursor shaders in Ghostty?
Clone the repository into the Ghostty shaders directory with `git clone https://github.com/sahaj-b/ghostty-cursor-shaders ~/.config/ghostty/shaders`, then add a `custom-shader` line per shader to your Ghostty config, pointing at the file name under the shaders directory.
How do I customise a cursor shader?
Each file has parameters like colour, duration, size and thickness as constants at the top, and a set of easing functions that control the animation curve. In trail shaders you comment and uncomment the easing functions in the code, in the pulse and boom shaders you do the same with the lines in the ANIMATION section, and you can add your own easing functions.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/sahaj-b-cursor-shaders)Was this useful?