Skip to content

c4rlo/runapp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

runapp

runapp is a Linux desktop application runner that launches the given application in an appropriate systemd user unit, according to systemd recommendations.

By running each application in its own systemd service, you avoid the risk of a single memory-hungry application taking down your entire compositor session, and you gain the ability to easily inspect applications via e.g. systemctl --user status <my-app>.

A great complement to runapp is uwsm, which provides an easy way to run your Wayland compositor as well as user services and applications under systemd.

In fact, runapp is inspired by uwsm app, which has a similar feature set. However, compared to it and other alternatives, runapp is very fast (native executable written in C++) and has minimal dependencies (only systemd, no Python, binary is <200K).

Installation

Prerequisites

Your systemd user instance must include some key environment variables needed to run graphical applications.

To verify this, check that the output of systemctl --user show-environment includes WAYLAND_DISPLAY (if using Wayland) or DISPLAY (if using Xorg), as well as anything else your compositor may require (e.g. Sway needs SWAYSOCK, i3 needs I3SOCK).

If something is missing, review your compositor setup; I recommend using uwsm and following its setup instructions, which will take care of everything.

Usage

Running an application via runapp is as simple as e.g. runapp firefox to run Firefox.

Or if you want to inspect the systemd unit, the -v/--verbose option is useful:

$ runapp -v zathura
Resolved executable zathura to /usr/bin/zathura
Launching [email protected]: ["zathura"].
Success.

$ systemctl --user status [email protected][email protected] - zathura
     Loaded: loaded (/run/user/1000/systemd/transient/[email protected]; transient)
  Transient: yes
     Active: active (running) since Sun 2025-10-12 19:46:49 UTC; 1min 27s ago
 Invocation: b39d29d98b684eed8e7a900fdb3fd86f
   Main PID: 49494 (zathura)
      Tasks: 8 (limit: 18644)
     Memory: 26.7M (peak: 32.7M)
        CPU: 334ms
     CGroup: /user.slice/user-1000.slice/[email protected]/app.slice/app-graphical.slice/[email protected]
             └─49494 zathura

Oct 12 19:46:49 localhost systemd[655]: Starting zathura...
Oct 12 19:46:49 localhost systemd[655]: Started zathura.
Oct 12 19:46:49 localhost zathura[49494]: info: Opening plain database via sqlite backend.
Oct 12 19:46:49 localhost zathura[49494]: info: No plain database available. Continuing with sqlite database.

$ systemctl --user stop [email protected] 

To see what else you can do, try runapp --help:

runapp [OPTIONS] COMMAND...
    Run COMMAND as a systemd user unit, in a way suitable for typical applications.
    Options:

    -v, --verbose: Increase output verbosity.
    -o, --scope:   Run command directly, registering it as a systemd scope;
                   the default is to run it as a systemd service.
    -i SLICE, --slice=SLICE:
                   Assign the systemd unit to the given slice (name must include
                   ".slice" suffix); the default is "app-graphical.slice".
    -d DIR, --dir=DIR:
                   Set working directory of command to DIR.
    -e VAR=VALUE, --env=VAR=VALUE:
                   Run command with given environment variable set;
                   may be given multiple times.

runapp --help
    Show this help text.

Or you can read the man page via man runapp.

Integrations

Probably you don't always want to type runapp firefox to run Firefox (for example).

A simple way to improve on this is to make a shell alias, function, or script with a short and memorable name that runs runapp firefox for you.

In addition, there are some other ways that applications are often launched:

Application launchers

Tell your launcher to run the selected applications via runapp.

  • Fuzzel: fuzzel --launch-prefix=runapp or add launch-prefix=runapp to the config file.
  • Rofi: rofi -show drun -show-icons -run-command 'runapp {cmd}'.

File managers

Tell your file manager to open a selected file in an application via runapp.

File openers

  • Rifle (part of Ranger): see Ranger above.

Various others, including xdg-open, are unfortunately not sufficiently customizable to allow interposing runapp.

Hotkeys

  • Sway: Configure e.g. bindsym Mod4+Return exec runapp foot to have it launch the foot terminal emulator under runapp on Super+Return.
  • Hyprland: Configure e.g. bind = SUPER, Return, exec, runapp foot for the same thing.

Features

  • Fast: native code (written in C++); talks directly to systemd, via its private socket if available, the same way that systemd-run does.
  • No dependencies beyond systemd.
  • Run app either as systemd service (recommended, default) or as systemd scope.
    • The latter means runapp directly executes the application, after registering it with systemd.
  • Run app either under app-graphical.slice (recommended for most cases, default) or under any other slice.
  • Option to run app in given working directory.
  • Option to run app with given environment variables.
  • If run from Fuzzel, derive unit name from .desktop name, per systemd recommendations.
  • On error, if not run from interactive terminal, show desktop notification.

Non-features

I don't consider these very important to have, but I'm open to discussions (feel free to open an issue!).

Alternatives

  • uwsm app: the original; somewhat slow due to being written in Python.
  • uwsm-app: shell script that ships with uwsm; spawns a background daemon.
  • app2unit: self-sufficient and feature-complete shell script by the author of uwsm.

Development

Prerequisites: GCC 15 or later with C++ compiler, and GNU Make.

  • make debug: create debug build.
  • make compile_commands.json: generate compile_commands.json file, useful for language servers like clangd; requires bear.
  • make release: create release build.
  • make clean: delete all build artefacts.
  • make install: install release build into /usr/local (or override via prefix variable).
  • make uninstall: delete installed release build.

About

Linux desktop application runner

Resources

License

Stars

Watchers

Forks