sahaj-b/ghostty-cursor-shaders

Custom cursor shaders for ghostty & kitty terminals (trails and ripple/pulse effects)

GLSL

1,158

16 commits

updated Oct 3, 2026

See the code

README

Cursor shaders for ghostty and kitty

WARNING: These are extremely customizable

Demos

EffectDemo
Cursor Warp
(Neovide-like)
cursor_warp
Cursor Sweepcursor_sweep
Cursor Tail
(Kitty-like)
cursor_tail
Ripple Cursorripple_cursor
Sonic Boomsonic_boom
Ripple Rectangleripple_rectangle
Customized
(faded warp + ripple)
customized_warp

Trails

  • 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
  • kitty ports (trails only): kitty/ (cursor-warp, cursor-sweep, cursor-tail)

Pulse/Boom effects

  • These trigger on cursor mode changes (block to line or vice versa, looks cool on changing modes in vim)
  • Ghostty only, kitty's shader API (0.49.2) exposes no cursor when the trail is inactive, so shape-only changes can't trigger these
  • 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

Usage

Ghostty

  1. Clone the repo into your ghostty shaders directory:
git clone https://github.com/sahaj-b/ghostty-cursor-shaders ~/.config/ghostty/shaders
  1. In your ~/.config/ghostty/config, add:
custom-shader = shaders/ghostty/yourshader1.glsl
custom-shader = shaders/ghostty/yourshader2.glsl
# ...

Replace yourshader with the name of any shader file (e.g., cursor_sweep, ripple_cursor, etc.)

Kitty (trails only, needs kitty >= 0.49)

  1. Copy the kitty/ folder into your kitty config:
cp -r kitty/* ~/.config/kitty/shaders/
  1. In your ~/.config/kitty/kitty.conf, add (pick ONE trail):
cursor_trail 1
custom_shaders cursor-warp
# custom_shaders cursor-sweep
# custom_shaders cursor-tail

The kitty cursor-warp ships with the customized (faded warp) values from below

Customization

  • 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 ANIMATION section
    • you can also add your own easing functions if you want

Example (faded warp + ripple)

// 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;

Acknowledgements

Inspired by Neovide cursor animations and KroneCorylus/ghostty-shader-playground

License

MIT

Why use branching(if/else) instead of branchless math

  • 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

sahaj-b/ghostty-cursor-shaders

Custom cursor shaders for ghostty & kitty terminals (trails and ripple/pulse effects)

GLSL

1,158

16 commits

updated Oct 3, 2026

See the code

README

Cursor shaders for ghostty and kitty

WARNING: These are extremely customizable

Demos

EffectDemo
Cursor Warp
(Neovide-like)
cursor_warp
Cursor Sweepcursor_sweep
Cursor Tail
(Kitty-like)
cursor_tail
Ripple Cursorripple_cursor
Sonic Boomsonic_boom
Ripple Rectangleripple_rectangle
Customized
(faded warp + ripple)
customized_warp

Trails

  • 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
  • kitty ports (trails only): kitty/ (cursor-warp, cursor-sweep, cursor-tail)

Pulse/Boom effects

  • These trigger on cursor mode changes (block to line or vice versa, looks cool on changing modes in vim)
  • Ghostty only, kitty's shader API (0.49.2) exposes no cursor when the trail is inactive, so shape-only changes can't trigger these
  • 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

Usage

Ghostty

  1. Clone the repo into your ghostty shaders directory:
git clone https://github.com/sahaj-b/ghostty-cursor-shaders ~/.config/ghostty/shaders
  1. In your ~/.config/ghostty/config, add:
custom-shader = shaders/ghostty/yourshader1.glsl
custom-shader = shaders/ghostty/yourshader2.glsl
# ...

Replace yourshader with the name of any shader file (e.g., cursor_sweep, ripple_cursor, etc.)

Kitty (trails only, needs kitty >= 0.49)

  1. Copy the kitty/ folder into your kitty config:
cp -r kitty/* ~/.config/kitty/shaders/
  1. In your ~/.config/kitty/kitty.conf, add (pick ONE trail):
cursor_trail 1
custom_shaders cursor-warp
# custom_shaders cursor-sweep
# custom_shaders cursor-tail

The kitty cursor-warp ships with the customized (faded warp) values from below

Customization

  • 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 ANIMATION section
    • you can also add your own easing functions if you want

Example (faded warp + ripple)

// 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;

Acknowledgements

Inspired by Neovide cursor animations and KroneCorylus/ghostty-shader-playground

License

MIT

Why use branching(if/else) instead of branchless math

  • 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

Significant stargazers

diniamo

25 followers · starred Mar 2026

rafareborn

165 followers · starred Oct 2025

Justin Garcia

173 followers · starred Oct 2025

Justin "J.R." Hill

121 followers · starred Nov 2025