Run-or-raise for KDE Plasma 6 (Wayland & X11): press a global shortcut to focus an app's window, or launch it if it isn't open — with a GUI to manage apps and shortcuts, and a CLI for automation.
Every app, its shortcut, and its launch command in one list — the banner up top confirms the daemon is live.
Status: early release (0.1.0) — works on my Plasma 6 machines; issues and testing on other distros welcome.
Run-or-raise isn't new — kjump exists to add the management layer the existing tools leave out. If you're weighing options:
ww-run-raise— the closest tool, and a real one: KDE-native (Plasma 5/6, Wayland + X11), using the same on-demand KWin-script trick kjump does. The difference is management — withwwyou wire up a KDE custom shortcut per command by hand, and there's no GUI. kjump adds exactly that missing layer: a GUI to manage the apps, and a daemon that registers its own shortcuts as a single KJump section in System Settings (central, persistent across restarts, editable there too).jumpapp— the classic, but X11-only; it doesn't work on Wayland.- A hand-written KWin script — per-app JavaScript with shortcuts wired up by hand, no config UI.
- Rolling your own — kglobalaccel + a KWin script per app. Doable,
but it's the gotcha-filled rabbit hole this project climbed out of
(documented in
CLAUDE.md).
Short version: if you want a bare CLI and don't mind wiring shortcuts
yourself, ww-run-raise is great. kjump is for when you want the apps
and their shortcuts managed in one place — with a GUI, and a
command-line trigger (kjump <entry>) for automation on top.
kjump is built around installed applications (.desktop entries),
not arbitrary commands — another deliberate difference from tools like
ww-run-raise. You add an app by picking it from your installed apps, and
kjump reads both its launch command and its window class(es) straight
from the .desktop entry. Two reasons this is intentional:
- You browse real apps, not binaries. Pick from a list of the
applications you actually have, instead of hunting through everything on
$PATH. - Window-class matching comes for free. Run-or-raise needs a window
class to find the right window, and that lives in the
.desktopspec — so kjump can seed it for you rather than making you dig it out by hand.
(Adding a raw executable by path — for something with no .desktop entry
— may come later. Contributions welcome.)
| File | Purpose |
|---|---|
kjumpd.py |
The daemon. Reads apps.json, registers shortcuts via kglobalaccel, raises windows via KWin's scripting D-Bus, launches commands when no window is found. |
kjump-config.py |
PySide6 GUI for editing apps.json. Talks to the daemon over D-Bus to apply changes. |
kjump.py |
CLI. kjump <entry> triggers run-or-raise from the command line — same effect as pressing the shortcut. For scripting/automation. |
kjump.desktop.in |
Hidden .desktop whose filename matches the kglobalaccel component id. System Settings → Shortcuts uses it for the section's icon and label. |
kjump-config.desktop.in |
User-facing .desktop for app launchers (KRunner etc.). |
Makefile |
make install to ~/.local/bin, make uninstall to undo. |
apps.example.json |
Sample apps.json to crib from. |
tests/ |
unittest tests for the pure logic — no KDE/D-Bus needed. |
CHANGELOG.md |
Release notes (Keep a Changelog format). |
LICENSE |
MIT. |
KDE Plasma 6, Python 3, and a few distro packages — the daemon uses
dbus-python and GLib, the GUI uses PySide6 and the Qt 6 qdbus CLI.
Install them from your distribution, not pip: dbus-python, PyGObject
and PySide6 build against system libraries (D-Bus, GLib, Qt) and are
painful-to-broken via pip, which is also why kjump runs on the system
python3 rather than a virtualenv.
# Fedora / RHEL
sudo dnf install python3-dbus python3-pyside6 python3-gobject qt6-qttools
# Debian / Ubuntu
sudo apt install python3-dbus python3-pyside6 python3-gi qdbus-qt6
# Arch
sudo pacman -S python-dbus pyside6 python-gobject qt6-toolsThe Qt 6 qdbus binary is named qdbus-qt6 on Fedora/Debian and qdbus6
on Arch; kjump-config uses whichever is present, so the differing
package names above are fine. make install runs a quick import + qdbus
check and points you back here if anything is missing.
On any KDE Plasma 6 machine:
git clone https://github.com/Phaengris/kjump.git
cd kjump
make install # copies binaries, installs systemd unit, starts daemon
kjump-config # add apps + assign shortcutsPress your shortcut. Done.
- Add an app — open
kjump-config, clickAdd…, pick from the installed-apps list (filter as you type), set a shortcut, OK. - Tweak window classes — for apps where the default-seeded classes
don't actually match (rare but happens), use
Pick from window…while the running window is in front. - Edit shortcuts in System Settings → Shortcuts also works — the
daemon listens for changes and syncs back to
apps.jsonso the GUI reflects the same state. - Reload after editing
apps.jsonby hand:qdbus-qt6 org.kjump.Daemon /Daemon org.kjump.Daemon.Reload
A couple of things to keep an eye on:
- Shortcut conflicts. kjump won't steal a shortcut that KDE or another app already owns — but there's no conflict warning yet, and it won't tell you when this happens: the binding just silently won't fire. If a shortcut you set doesn't work, the combo is probably already taken — check System Settings → Shortcuts, or pick a different one.
- Review auto-filled window classes. kjump seeds an app's classes from
its
.desktopentry, which occasionally includes a generic class (e.g.firefoxfor a Firefox-based PWA). A too-generic class can match the wrong window — glance at Window classes when adding wrappers or PWAs and trim anything overly broad. Rare, but worth a look.
Add… opens a picker over everything installed — filter as you type
(the parenthesised text is the resource class kjump will match on):
Editing an entry lets you tune the window classes and the shortcut — or grab the class straight from a live window with Pick from window…:
kjump registers its own kglobalaccel component, so every binding shows up
as a single KJump section under System Settings → Shortcuts — a
first-class entry alongside Dolphin, Konsole and friends, editable right
there (the daemon syncs changes back to apps.json):
kjump <entry> does the same thing as pressing an entry's shortcut —
raise a matching window, or launch the command if none is open. <entry>
is an entry's id or name (case-insensitive), so both of these work:
kjump firefox # by id
kjump Firefox # by name
kjump --list # show configured entries (id and name)This makes kjump usable for automation without binding a global
shortcut — call it from a shell script, a KRunner alias, a hardware-key
mapping, ydotool, etc. It just talks to the running daemon over D-Bus;
if the daemon isn't running it tells you (systemctl --user start kjumpd). Exit status is 0 on a successful trigger, 1 if no entry matched
or the daemon is down — handy in scripts.
make uninstall # removes binaries, systemd unit, and kjump's
# entries from System Settings. apps.json
# at ~/.config/kjump/ is preserved.Installation is deliberately just a per-user make install / make uninstall (into ~/.local, no root) for now — no RPM, .deb, AUR, or
Flatpak. This is a young, single-author tool, and I'd rather not carry the
overhead of maintaining distro packages until there's real demand for one.
Want a proper package for your distro? Open an issue and let me know;
if there's interest I'll consider making one.
(Flatpak specifically is unlikely to work: the daemon needs unsandboxed access to kglobalaccel and KWin's D-Bus, which the Flatpak sandbox is designed to prevent.)
~/.config/kjump/apps.json:
{
"apps": [
{
"id": "firefox",
"name": "Firefox",
"command": ["firefox"],
"resourceClasses": ["org.mozilla.firefox", "firefox"],
"shortcut": 268435540,
"icon": "firefox"
}
]
}id: stable identifier (don't rename casually — kga keys off this).name: friendly label, free to change.command:subprocess.Popenargv.resourceClasses: list of strings; KWin script tries each against the window'sresourceClass. Worth listing several variants (e.g.org.mozilla.firefoxfor native Wayland ANDfirefoxfor X11).shortcut: Qt key code (MetaModifier | Key_T = 0x10000054). 0 = no binding.icon: optional.desktopIcon name, used in the GUI's table.
- A change made via System Settings while the daemon is stopped is preserved on next start (kga wins) — but a binding cleared in the GUI while the daemon was about to be stopped, then started again, could resurrect from kga. Edge case; document or fix later.
- No "duplicate this app" button yet — useful when you want the same app on two shortcuts (e.g. one global, one context-specific).
- No pre-save shortcut-conflict warning — kjump refuses to override a combo already owned by KDE or another app, but doesn't surface it in the GUI; the binding just silently won't fire. Warning before save is planned.
- No way to add a raw executable by path yet — entries are seeded from
.desktopapps (see Apps, not commands). Planned; contributions welcome.
systemctl --user stop kjumpd # release the BusName
./kjumpd.py # run from source, journal in terminal
# Ctrl+C when done
systemctl --user start kjumpd # back to installed versionThe installed copy is the "stable" runtime; running from source is the "dev" runtime. They can't fight: the daemon refuses to start when the BusName is owned (and exits 0, no restart loop).
Unit tests cover the pure logic (shortcut matching, config validation,
key-sequence unwrapping, the qdbus resolver) — no KDE or D-Bus needed,
so they run anywhere:
python3 -m unittest discover -s tests # or: pytest tests/The live behaviour (a keypress actually raising a window) needs a running
Plasma session and is verified by hand — see CLAUDE.md → Testing.
See CLAUDE.md for design rationale + accumulated kglobalaccel/KWin
gotchas.
Contributions and feedback are welcome — issues, PRs, and testing on other distros all genuinely help.
That said, kjump is intentionally opinionated: it does one thing, a particular way, and aims to stay small and focused. I may decline feature requests or PRs that don't fit that idea — nothing personal, no hard feelings 🙂. If you'd like it to work differently, forking is always fair game (it's MIT).
MIT — see LICENSE. Copyright (c) 2026 Phaengris.




