-
Notifications
You must be signed in to change notification settings - Fork 0
Launchers
A launcher is the executable Kartend hands an item to when you
press Enter (or double-click). It can be xdg-open, mpv, a libretro
runtime, a wrapper script, or anything else that takes a file path on
the command line.
Each collection has at minimum one launcher (the primary) and can
add any number of additional launchers for the same library — useful
when one set of items can be opened with multiple tools (a video file
that you sometimes run in mpv and sometimes in vlc, for example).
Configurations can be saved as presets and reused across
collections, and individual items can override the default choice via
right-click.
Where to find this — Settings Dialog → Launcher tab. INI keys:
launcherPath,launchParameters,corePath,launcherName,additionalLaunchers,defaultLauncherIndex, and[General] launcherPresets.
When you trigger a launch, Kartend:
- Resolves which launcher to use — primary, an additional, or a per-item override. See Selection rules.
- Builds an argument list (no shell):
<launchParameters>, followed by-L <corePath>if the launcher path matches a libretro-style binary, followed by the absolute path to the item file. - Spawns the process with
QProcess. By default Kartend detaches and forgets it; with Runtime Detection enabled (see Splash & Now Playing) Kartend tracks the child's lifetime instead. - Records the launch in the database (per-item
play_countincrements,last_playedtimestamp, optional history row). See History & Statistics.
Arguments go through a QProcess argument list. There is no shell
interpolation: ~, $VAR, &, >, quote rules, glob patterns —
none of them work the way they would in bash. If you need shell
behavior, point the launcher at a small wrapper script:
#!/bin/sh
# /usr/local/bin/kartend-mpv-fullscreen
exec /usr/bin/mpv --fs --really-quiet "$1"launcherPath=/usr/local/bin/kartend-mpv-fullscreenSpaces and ampersands in file paths are handled correctly without quoting because each argument is passed as a separate array element. You don't need to wrap launch parameters in quotes either.
The selected item's absolute path is appended last by default. If
your launcher needs the path elsewhere — say, after a --media flag —
use a wrapper script:
#!/bin/sh
exec /usr/bin/some-tool --media "$1" --extra-flagThere's no built-in {path} placeholder syntax in launchParameters
today.
The required-by-default launcher. Set on the Launcher tab:
| Field | INI key | Notes |
|---|---|---|
| Launcher Path | launcherPath |
Executable. Absolute path recommended. |
| Launcher Name | launcherName |
Display name in the multi-launcher chooser. Empty falls back to the basename of launcherPath. |
| Core Path | corePath |
RetroArch / libretro core (only used for libretro-style launchers). |
| Launch Parameters | launchParameters |
Arguments passed before the file path. |
Examples:
# xdg-open: opens with the user's default app for the file type
[Documents]
launcherPath=/usr/bin/xdg-open
# mpv with fullscreen
[Movies]
launcherPath=/usr/bin/mpv
launchParameters=--fs --really-quiet
# RetroArch + libretro core
[Retro Library]
launcherPath=/usr/bin/retroarch
corePath=/usr/lib/libretro/some_libretro.so
launchParameters=--fullscreen
# Standalone wrapper (no core)
[Audiobooks]
launcherPath=/usr/bin/mpv
launchParameters=--no-video --save-position-on-quitA collection can have a list of additional launchers in addition to the primary. They appear in the multi-launcher chooser dialog and let you pick at launch time which one to use.
[Films]
launcherPath=/usr/bin/mpv
launcherName=mpv
# additionalLaunchers is serialized; one row per additional entry.
# In practice this is managed via the Settings → Launcher tab.Settings dialog flow:
- Open Launcher tab → Additional Launchers list.
- Click Add Launcher to open the Launcher Editor Dialog.
- Fill in name / path / core / parameters (or pick a preset).
- Save. The new launcher appears in the list.
The combined list (primary + additional) is what the multi-launcher chooser presents and what per-item overrides reference. See Default launcher index for which one is pre-selected.
defaultLauncherIndex (default 0 = primary) controls the
pre-selection in the chooser dialog and the launcher used for items
without a per-item override.
[Films]
launcherPath=/usr/bin/mpv
launcherName=mpv
defaultLauncherIndex=1 ; vlc (additional[0]) is the default insteadThe Settings tab gives you a Default Launcher dropdown that lists the same options.
When a collection has more than one launcher, you can launch with a non-default by:
- Right-click → Always launch with… on a specific item — opens the Launcher Chooser Dialog with the current default pre-selected. Picking a launcher creates a per-item override (stored in the database, not in the INI file).
- A future "ad hoc launch" workflow may let you pick once without saving an override; today every chooser pick saves.
To remove a per-item override, right-click → Clear launcher override.
Modal radio-button list of all launchers for the current collection.
- Pre-selects the current default (or the existing override).
- Description below each entry shows the resolved name + path + core + parameters (preset references are resolved live).
- OK / Cancel.
Presets are reusable launcher configs that live in [General], not
per-collection. Useful if you have, say, the same mpv --fs --really-quiet
config on twelve different movie collections.
[General]
launcherPresets=... ; serialized list of presets, managed via the UIA preset has:
-
id— UUID. Stable across rename. References use the id, not the name. -
name— display label. -
launcherPath,corePath,launchParameters— same shape as a regular launcher.
A launcher entry that references a preset stores the preset's id
on its presetId field. At launch time, Kartend resolves the preset
and uses its values; if the preset is deleted, Kartend falls back to
any inline values on the launcher entry.
Settings → Launcher tab → Global Launcher Presets section. Add, rename (safe — references are by id), edit, or delete.
Renames update the display label everywhere instantly without breaking
any references — entries stored the id, not the name.
In the Launcher Editor Dialog, set Preset to a preset id. The inline path / core / parameters fields gray out — the preset overrides them. Clear the preset reference to switch back to inline config.
RetroArch is supported as a special case because its CLI takes a core
via -L:
retroarch -L <corePath> <fullscreenFlags> <fileName>
Kartend detects "RetroArch-style" launchers by checking whether the
launcher path's filename contains retroarch (case-insensitive). If
so, corePath is automatically passed as -L <core>. Examples that
match: /usr/bin/retroarch, ~/bin/retroarch.AppImage,
retroarch.exe. Examples that don't: mednafen, pcsx2, dolphin.
For non-RetroArch launchers corePath is ignored — leave it blank.
Some cores can't open zipped content directly. Set the extraction options on the Paths & Extensions tab:
| Setting | INI key | Notes |
|---|---|---|
| Extract Archives | extractArchives |
Boolean toggle |
| Extracted Extension | extractedExtension |
Which extension inside the archive to launch (e.g. pdf, cbz) |
When enabled and the selected item is an archive (.zip, .7z, …),
Kartend extracts to a temporary directory under ~/.cache/kartend/,
finds the first file matching extractedExtension, and launches that
file instead of the archive. Temp directories are cleaned up on
shutdown.
If the archive contains nothing matching extractedExtension, the
launch fails with an error dialog.
Items remember which launcher you "always launch with" via the database, not the INI:
- Right-click → Always launch with… opens the chooser; pick one to set the override.
- Right-click → Clear launcher override removes it; the collection default takes effect again.
- Override is keyed by
(collection_uuid, source_path)so it survives rescans and persists across rename of the source file (assuming you don't move it).
The right-click options appear only when a collection has more than one launcher (otherwise there's nothing to choose).
Kartend performs basic validation before launching:
- The launcher path must point to an existing, executable file.
- The launcher path is re-validated immediately before
QProcess::startto mitigate TOCTOU (time-of-check / time-of-use) attacks where the file is swapped between Kartend's first check and the actual launch. - A blacklist blocks launches where the item path falls under known
sensitive system directories (
/,/etc,/root,/proc,/sys,/dev, etc.) — these are rejected with an error dialog. The launcher itself can still live anywhere. - All arguments go through
QProcess's argument list, never through a shell. There's no command injection surface from item filenames or launch parameters.
If a launch fails, an error dialog reports which step failed (path validation, executable check, process start) and the reason.
If your launcher is CLI-only, wrap it in a terminal:
#!/bin/sh
# /usr/local/bin/kartend-cli-tool
exec konsole -e /usr/bin/some-cli-tool "$1"If the same collection has files of different types (e.g. .pdf and
.cbz mixed), use a dispatcher script as the launcher:
#!/bin/sh
# /usr/local/bin/kartend-multi-launcher
case "$1" in
*.pdf) exec /usr/bin/okular "$1" ;;
*.cbz) exec /usr/bin/krita "$1" ;;
*) exec xdg-open "$1" ;;
esaclaunchParameters is split into argv on whitespace. To embed a literal
space inside one argument, use a wrapper:
launchParameters=--title MyApppasses two args: --title and MyApp. To pass My App as a single
argument you'd need a wrapper script.
launcherPath=/home/me/builds/retroarch
corePath=/home/me/builds/cores/some_libretro.so
launchParameters=--fullscreen --verboseWhen a launch fails silently or behaves unexpectedly, Launch Preview shows you exactly what Kartend would run without actually running it. Open via the per-item right-click menu → Preview launch command….
┌────────────────────────────────────────────────────────────┐
│ Launch preview │
│ │
│ Program: /usr/bin/mpv │
│ Arguments: │
│ --fs │
│ --really-quiet │
│ "/home/me/Videos/Films/Some Movie (2021).mkv" │
│ Working directory: /home/me/Videos/Films │
│ │
│ Warnings │
│ ⚠ Argument 2 contains shell metacharacters — Kartend │
│ will pass it without quoting; the launcher must │
│ handle it. │
│ │
│ [ Close ] │
└────────────────────────────────────────────────────────────┘
What it shows:
- Program — the resolved launcher executable.
-
Arguments — the full argv as Kartend would hand it to
QProcess::start, with one argument per line. No shell expansion is performed; what you see is what gets passed. -
Working directory — the cwd
QProcesswill use (typically the item's media directory). -
Archive extraction — when
extractArchives=trueand the item is a.zip/.7z/.rar, the preview adds the resolved extracted-file path that Kartend would launch instead. - Warnings — validation flags surfaced before the actual launch: missing file, launcher not found, suspicious characters, launcher-flag conflicts.
Useful when iterating on launcher arguments (you don't want to keep firing a real launch just to verify the command line), and as a self-service first stop when "the item won't launch" — the warnings list usually explains why.
| Symptom | Likely cause | Fix |
|---|---|---|
Nothing happens on Enter
|
Empty launcherPath
|
Set the launcher in Settings → Launcher. |
| "Launcher not executable" | Launcher path isn't +x
|
chmod +x /path/to/launcher or pick a different launcher. |
| Launcher opens but the file doesn't load | Launcher expects the file at a non-final position | Use a wrapper script that re-arranges arguments. |
Item with & or spaces in name fails |
(Unlikely — should work. Check the launcher's own escape rules.) | Confirm the launcher's CLI handles special characters; wrap if not. |
| RetroArch launches without a core |
corePath empty or filename doesn't contain "retroarch" |
Set corePath; verify the launcher path includes "retroarch". |
Archive launches the .zip instead of the contained file |
extractArchives=false or extractedExtension wrong |
Enable extraction and set the right extension. |
| "Always launch with…" missing from menu | Collection only has one launcher | Add at least one additional launcher. |
- Launch pipeline: src/modules/input/launch/
(
LaunchManager, validators,LaunchUtils). - Preset resolution:
LauncherUtils::resolvePreset(config, presets)in src/utils/app/collection/launcherconfig.h — call this before reading path/core/params from a launcher entry. - libretro detection:
LauncherUtils::usesLibretroCore(path). - Per-item override storage:
item_metadata.launcher_indexin SQLite (see Item Metadata). - TOCTOU re-validation:
LaunchManager::launchItem()callsvalidateLaunchPath()twice — once at queue time, once immediately beforeQProcess::start. - Sensitive-directory blacklist:
LaunchPathValidatorin the launch module. - Adding a new launcher field (e.g. environment variables): extend
LauncherConfigin src/utils/app/collection/launcherconfig.h, add UI inlaunchereditordialog, propagate through serialization insettingsmanager, and update Configuration Reference.