| Effect | Demo |
|---|---|
| Cursor Warp (Neovide-like) |
![]() |
| Cursor Sweep | ![]() |
| Cursor Tail (Kitty-like) |
![]() |
| Ripple Cursor | ![]() |
| Sonic Boom | ![]() |
| Ripple Rectangle | ![]() |
| Customized (faded warp + ripple) |
![]() |
- cursor_warp.glsl: Neovide-like cursor trail, most customizable shader
- cursor_sweep.glsl: Animated trail that shrinks from previous to current cursor position
- cursor_tail.glsl: Comet-like trail, mimicing kitty terminal's cursor_trail effect
- These trigger on cursor mode changes (block to line or vice versa, looks cool on changing modes in vim)
- sonic_boom_cursor.glsl: expanding filled circle
- ripple_cursor.glsl: Expanding circular ring ripple effect
- rectangle_boom_cursor.glsl: Same as boom_cursor but rectangular(cursor shape)
- ripple_rectangle_cursor.glsl: Same as ripple_cursor but rectangular(cursor shape)
Note
If you have the line cursor (default), these effects will trigger and freeze on unfocus(as cursor changes to hollow block). The solution is to add custom-shader-animation = always to your ghostty config
- Clone the repo into your ghostty shaders directory:
git clone https://github.com/sahaj-b/ghostty-cursor-shaders ~/.config/ghostty/shaders- In your
~/.config/ghostty/config, add:
custom-shader = shaders/yourshader1.glsl
custom-shader = shaders/yourshader2.glsl
# ...
Replace yourshader with the name of any shader file (e.g., cursor_sweep, ripple_cursor, etc.)
- All shaders has customizable parameters (like color, duration, size, thickness, etc) etc at the top of each file. You can adjust
- Also, all files has various Easing Functions to choose from.
- these function control the animation curve of the effects, you can make them elasitcy, springy, smooth, linear, etc by changing the easing function
- in trail shaders, you can comment/uncomment the easing functions in the code
- in pulse/boom shaders, you can comment/uncomment the lines in the
ANIMATIONsection - you can also add your own easing functions if you want
// 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;
const float TRAIL_THICKNESS_X = 0.9;
const float FADE_ENABLED = 1.0;
const float FADE_EXPONENT = 5.0;// in ripple_cursor.glsl
const float DURATION = 0.15;
const float MAX_RADIUS = 0.026;
const float RING_THICKNESS = 0.02;
const float CURSOR_WIDTH_CHANGE_THRESHOLD = 0.5;
vec4 COLOR = vec4(0.35, 0.36, 0.44, 0.8);
const float BLUR = 3.5;
const float ANIMATION_START_OFFSET = 0.01;Inspired by Neovide cursor animations and KroneCorylus/ghostty-shader-playground
MIT
- coz we are dealing with uniform branching here, which has NO DIVERGENCE.
- ie, all fragments will take the same branch path, so no performance penalty on modern GPUs
- Branchless math would force GPU to calculate animations every single frame, even when there is no need






