Skip to content

Repository files navigation

kjump

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.

The kjump main window: a table of apps with their shortcuts and launch commands, and a banner showing the daemon is running

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.

Alternatives, and why this exists

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 — with ww you 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.

Apps, not commands

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 .desktop spec — 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.)

What's in here

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.

Prerequisites

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-tools

The 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.

Quick start

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 shortcuts

Press your shortcut. Done.

Daily life

  • Add an app — open kjump-config, click Add…, 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.json so the GUI reflects the same state.
  • Reload after editing apps.json by 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 .desktop entry, which occasionally includes a generic class (e.g. firefox for 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.

Adding and editing apps

Add… opens a picker over everything installed — filter as you type (the parenthesised text is the resource class kjump will match on):

The Add-app dialog showing an alphabetical list of installed applications with their icons and resource classes

The same picker filtered to "dol", narrowed to a single Dolphin result

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…:

The edit dialog for Dolphin: name, command, window classes, a Pick-from-window button, and a shortcut field showing Meta+D

One section in System Settings

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):

System Settings → Shortcuts with the KJump section selected, listing every kjump app and its Meta+ binding

Triggering from the command line

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.

Removing it

make uninstall                # removes binaries, systemd unit, and kjump's
                              # entries from System Settings. apps.json
                              # at ~/.config/kjump/ is preserved.

Packaging

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

~/.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.Popen argv.
  • resourceClasses: list of strings; KWin script tries each against the window's resourceClass. Worth listing several variants (e.g. org.mozilla.firefox for native Wayland AND firefox for X11).
  • shortcut: Qt key code (MetaModifier | Key_T = 0x10000054). 0 = no binding.
  • icon: optional .desktop Icon name, used in the GUI's table.

Known issues / TODOs

  • 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 .desktop apps (see Apps, not commands). Planned; contributions welcome.

Development loop

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 version

The 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).

Tests

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.

Contributing

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).

License

MIT — see LICENSE. Copyright (c) 2026 Phaengris.

About

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

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages