One of the best “productivity” hacks that I use on my machine is creating keybindings to swap between commonly used apps. On mac I used Karabiner together with some apple script. On Linux I use various scripts like wmctrl -x -a Firefox different keybindings for different apps. I tend to use Super+Shift+Letter for these bindings and then use Super+Alt+Letter for bindings related to “desktop actions”.
I’m using KDE at the moment in which creating these shortcuts is fairly straightforward. In the past, I have used tiling window managers such as i3 and lua where this is equally straight forward.
The keybindings I use
I end up have a shortcut for: Firefox, Obsidian, a terminal, and Emacs. For other things I fall back to using rofi which provides a fuzzy switcher based on window titles
Ensuring that the PATH is set correctly
One consistent annoyance is ensuring that the path is set correctly when an application is launched by the window manager.
I have two tricks here.
First you can use env -i command to run a command with an empty environment from the shell - you can then make sure that your command will work regardless of the environment that your window manager provides.
I also have a wrapper called withbashrc which runs bashrc and then runs a command so that everything I add to my bashrc is still on my path when I run something.
#!/bin/bash
export PATH=$PATH:/usr/bin:~/.extraconfig/bins/pathmerge
export HOME=~
export NO_SSH_AGENT
source ~/.bashrc
"$@"
I use this like withbashrc command
Cycling windows
wmctrl works well enough, provided you have precisely one window. I tend to do this because it makes switching app windows… but I’m experimenting with having a couple of Obsidian windows open at the moment while working on some tools for reading. For this, I have a solution where I order all windows arbitrarily and then cycle to the next unfocused Obsidian if I press the “raise Obsidian keybinding again”.
Because the output of wmctrl didn’t have all the informaion I needed (namely the window class) in its output from wmctrl -l I ended up writing my own link wmctrl that output json information and had an option --next-unfocused to cycle through windows. I put this in pip and on github so it is available everywhere.
I then used the following command:
json-wmctrl --class "obsidian" --next-unfocused | jq .id | xargs wmctrl -i -a
Which either raised the first obsidian window or cycles through the windows.
Open that app if it not running
The world is simpler if you have fewer concepts and fewer moving parts, so it can be simpler if you use the same keybinding to both open an app and raise it. I haven’t gotten around to get this working when also cycling between windows, though this wouldn’t take too much work.
If you only have a single window for an app a nice approach is to use the raise-or-run command line-tool, written in Rust. You can install this with:
cargo install run-or-raise
(If you search on github, you will find a lot of different run-or-raise programs!).
I then use the following command to, for example, start or raise the brave browser. I use json-wmtrl as above to get the class for this query.
run-or-raise 'class = "Brave-browser"' brave-browser
Finishing up
So I’ve documented the tricks I use. I have this is useful. If you find this interested you might like to:
Have a look at this command-line to list windows in JSON that I made.
Have a look at my review of how people use Obsidian for note taking. I find maintaining a bit of a “second brain” to hold my hands while doing work quite handy and this summarize some use cases.
I am readwithai. I make tools related to reading, agency and productivity often related to Obsidian and write a bit about this.
If any of this seems interesting you can follow me on X where I often post about cli / linux tricks, or follow me on my blog where I intend to post more about work related to Obsidian - part form this selection.