Basically KurtVelasco's Desktop Gremlin, but re-written in PySide + Qt6.
output.mp4
π₯ Features π₯
- Works on both X11 (with picom) and Hyprland (with XWayland).
- Also works on Windows and MacOS (follow the manual installation guide).
- Interactive controls:
- Drag & Drop: π±οΈ Click and drag your gremlins to move 'em.
- Walk: β¨οΈ
Cursor-following does not work in Wayland π₯Ίπ₯Ίπ₯Ί. So hover your mouse over the gremlins, then use W/A/S/D to make 'em skedaddle π¨π¨. - Secret Move: Right-click to see what happens π. Pro tip: where you right-click matters! A headpat, a poke, (or something even more special) might play!
- Also, if you leave the gremlins lonely for so long, they will occasionally make more β¨noisesβ¨ to annoy you ππ. Think of it as "1 hour of silence occasionally broken up by Mambo".
Note 1: The "1 hour of silence occasionally broken up by Mambo" feature can be turned off (if you are a chicken ππ). See the "Customize your Gremlins!" section below.
Note 2: It seems that the "Cursor-following does not work in Wayland" statement of mine was, in fact, a skill issue π©π©.
- 2025-11-18: Massive source code restructure! We now have a unified run script and a package recipe for Guix. (Huge thanks to @thanosapollo! This chad is a much better programmer than I am.)
- 2025-11-16: Added a manual trigger for the annoy emote. Press
Pto make them noisy on command. - 2025-11-15: Remapped headpats from Left Click to Right Click. No more accidental pats when you want to drag them around!
This is not a strict 1:1 port, because I made some changes to the animation flow to better match my own preferences. I also created a few additional spritesheets; please feel free to use them if they're helpful.
Furthermore, for anyone who wants to add or change the animation logic: Check out the animation_tick method in gremlin.py. Unlike KurtVelasco's original code, this version uses a more traditional Finite State Machine design, so it should make the logic easier to follow and extend. There's still plenty of room for improvement, though. I'll come back to polishing the code after I finish adding the animations I have in mind.
To make the gremlin's background transparent, your compositor must be configured correctly. Unfortunately, this is not something that can really be automated. So, before you install, please follow these guides for X11 desktops and Hyprland:
For X11 (e.g., i3, bspwm, etc.)
Install picom and have it executed on startup is enough. For example, you may install it via:
sudo apt install picom # for Debian/Ubuntu based distros
yay -S picom # for AUR usersThen, add the following line into your ~/.xinitrc or equivalent startup script:
picom &For Hyprland
Firstly, you need xwayland. Since you're using Hyprland, I suspect you have it already. But if you don't, please install it with this command (or any of its equivalent):
yay -S xorg-xwaylandThen, add the following rules into your ~/.config/hypr/hyprland.conf:
windowrulev2 = noblur, title:ilgwg_desktop_gremlins.py
windowrulev2 = noshadow, title:ilgwg_desktop_gremlins.py
windowrulev2 = noborder, title:ilgwg_desktop_gremlins.py
For Niri
Add the following window rules:
window-rule {
match title="ilgwg_desktop_gremlins.py"
draw-border-with-background false
opacity 0.99
focus-ring {
off
}
border {
// Same as focus-ring.
}
shadow {
off
}
}
Just run the following script, and it will take care of the rest:
# this will install to ~/.config/linux-desktop-gremlin/
curl -s https://raw.githubusercontent.com/iluvgirlswithglasses/linux-desktop-gremlin/refs/heads/main/install.sh | bashIt is recommended that you check the content of the script before running.
If you have rofi installed, you can use it to find and run Desktop Gremlin.
Otherwise, you can navigate to ~/.config/linux-desktop-gremlin/ and execute the run script, then a gremlin shall be spawned:
./run.sh # to spawn the default character (specified in ./config.json)
./run.sh <character-name> # to spawn any character who is available in ./spritesheet/
# You can now close the terminal which you executed these scripts with.
# The gremlin won't be despawned unless you use your hotkeys for closing window,
# like alt+f4 or mod+q.You can install dependencies either in a Python virtual environment or using your system's package manager.
Method A: Virtual Environment (Recommended)
There's nothing that can go wrong about this, except for the disk space. This also works on Windows and MacOS.
# clone repository
git clone https://github.com/iluvgirlswithglasses/linux-desktop-gremlin
cd linux-desktop-gremlin
# install uv -- a fast Python package manager -- then sync packages
curl -LsSf https://astral.sh/uv/install.sh | sh
uv syncMethod B: System Package Manager
This method uses your distribution's packages to save disk space. You will need PySide6 and its Qt6 dependencies.
# Example for Arch Linux
yay -S pyside6 qt6-baseExecute one of these run scripts, then a gremlin shall be spawned:
./run.sh # to spawn the default character (specified in ./config.json)
./run.sh <character-name> # to spawn any character who is available in ./spritesheet/
./scripts/gremlin-picker.sh # if you want to use a GUI picker (you need rofi installed)
# You can now close the terminal which you executed these scripts with.
# The gremlin won't be despawned unless you use your hotkeys for closing window,
# like alt+f4 or mod+q.You would also need to configure your compositor correctly so that the gremlins have fully transparent background. Refer to section "How to Install and Run (Automatically)" > "1. Configure your Compositor".
output.mp4
Do you want the gremlins to annoy you at random time or not? π
To control this, open ./spritesheet/<character>/emote-config.json. You'll see:
{
"AnnoyEmote": true,
"MinEmoteTriggerMinutes": 5,
"MaxEmoteTriggerMinutes": 15,
"EmoteDuration": 3600
}If you set AnnoyEmote to false, then nothing happens. If you set it to true, however:
- If the gremlin goes without any "caring interactions" (no pats, no drags, no clicks,...) they will get bored π’.
- If you leave them bored for a while (a random time between
MinEmoteTriggerMinutesandMaxEmoteTriggerMinutes), they will suddenly play a special emote (with sound!) all by themselves ππ. - The emote will last for the number of milliseconds set in
EmoteDuration.- (Note: For now, this duration only affects the animation, not the sound effect, sorry π’.)
You can also trigger this animation by hovering over the gremlin and press "P". You can customize this key too, just take a look at ./config.json.
This program's systray is disabled by default, and you won't lose any functionality by disabling the systray either. However, if you need it, you might enable it by modifying the Systray field in ./config.json to true.
There are some forks of this repository that you may want to checkout!
- #23: Significantly reduces memory usage of the app, though some functionalities will be different.
I'll be adding more characters as soon as my full-time job and university decide to give me a break.
Also, got a cool spritesheet you're dying to see running on your desktop? Feel free to open an issue on GitHub and share! Thank you!