When first moving to i3 as a window manager, you may have relished the opportunity to learn a tonne of new shortcut keys on your journey to being the neckbeardiest of them all (I know I certainly did). At some point along the way, you probably realised that it would be useful to start certain programs/scripts when you first login. As this is linux, there’s about 15 different ways to do this, but I’m going to show you my favourite. It’s my favourite for a few reasons:

  • You can keep all of your startup scripts in one place (likely ~/.config/i3/scripts if you’re following my example)
  • If you ever close one of these and want to start them again, just hit your i3 config reload key (mod + shift + r if you’re using my dotfiles)
  • If you ever need to modify the way that the program is launched, you just have to tweak the script, no extra lines in your i3 config file


  • Your i3 config file (hopefully ~/.config/i3/config)
  • The ability to write a shell script (may I recommend Neovim for even more neckbeard clout)


1 - Create a Shell Script

So the way we’re going to do this is to run a shell script from within our i3 config, then the shell script is going to run the program. You could just add the program itself as a line in your i3 config file but there’s 2 major benefits to doing it this way:

  • PID detection - we don’t want to run a new copy of the program every time we reload our i3 config, that will get messy fast
  • Less clutter in the i3 config - the i3 config file is already a bit of chunky one, let’s not add to that, eh?

Using your editor of choice create a new Shell script (I’m using this to launch Nextcloud, hence the below):

if [[ ! $(pgrep -u $UID -x nextcloud) ]]; then
        nextcloud &

All this is doing is using pgrep to check for a PID already launched by your User ID, to avoid double/triple/etc launching the same thing. If that’s not found, it will launch a new instance of that (and background it with & otherwise the script will hold up the loading of i3, which nobody wants). It’s worth mentioning that if the process has a different name than you’re expecting then this will fail. Best to run pgrep -u $UID -x PROCESS_NAME when it’s active just to be sure

2 - Add a Reference to the i3 Config File

Add the below to your i3 config file, assuming your script is in the same location as mentioned above (mine is below my Polybar config but you can just stick it at the end):

exec_always --no-startup-id $HOME/.config/i3/scripts/YOUR_SCRIPT.sh

Now reload i3 and viola, your program has launched. Now reload it again, maybe even a few times. You should notice that if it’s already launched, the i3 reload won’t relauch it, but if you close it the reload will launch it. Magic!