Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: March 27, 2025
In this tutorial, we’ll discuss how to start an application on a specific workspace in the i3 tiling window manager. This way, we can automate workflows involving different i3 workspaces.
There are three scenarios we’ll cover that are related to each other since they relate to applications and workspaces. We may want to have a set of applications in some workspaces when we start our system, we may want to open an application in a particular workspace, or we may want to save a layout and restore it in the future.
As always, when configuring with i3, it’s worth remembering that we’ve got some logging available to help us debug whenever our configuration is not working as expected. Through these logs, we can diagnose and fix problems with our i3 environment configuration.
There are several methods, but if we want to open an application at startup in a specific workspace in i3, we need i3-msg.
For example, imagine we want to open xterm in workspace 2. We’ll need to add the following line to our configuration file for i3 (usually located in ~/config/.i3/config):
exec --no-startup-id "i3-msg 'workspace 2; exec /usr/bin/xterm'"
We call exec to execute the i3-msg command and the application we want. We’re using the –no-startup-id flag to disable the notifications during the startup for this exec command. This way, we won’t get a temporary window until our program has finished launching, and meanwhile, the cursor will change to a clock.
The solution should work out of the box, and we should have xterm in the second workspace. However, this solution may not work when we request several applications in a row, and some of those applications take a long time to load.
For example, let’s consider the following snippet:
exec --no-startup-id "i3-msg 'workspace 1; exec quick-to-load-application'"
exec --no-startup-id "i3-msg 'workspace 1; exec another-quick-to-load-application'"
exec --no-startup-id "i3-msg 'workspace 2; exec slow-to-load-application'"
exec --no-startup-id "i3-msg 'workspace 3; exec yet-another-quick-to-load-application'"
In this snippet, we are requesting several applications in several workspaces. The application of workspace 2, slow-to-load-application, will take a long time to load. Thus, i3 will launch it and continue to the following command before the application is fully launched. We may end up with the slow-to-load-application and yet-another-quick-to-load-application both in workspace 3, which we didn’t want.
The easiest solution would be to reorder the execution calls based on the expected time of their execution:
exec --no-startup-id "i3-msg 'workspace 1; exec quick-to-load-application'"
exec --no-startup-id "i3-msg 'workspace 1; exec another-quick-to-load-application'"
exec --no-startup-id "i3-msg 'workspace 3; exec yet-another-quick-to-load-application'"
exec --no-startup-id "i3-msg 'workspace 2; exec slow-to-load-application'"
This way, the application that takes longer to load is the one called the last, so i3 doesn’t switch workspaces anymore.
However, this won’t work if we have several applications that take a long time to load. In those cases, we’ll need to add a small delay with sleep to allow for the application to load before moving to the next workspace:
exec --no-startup-id "i3-msg 'workspace 1; exec quick-to-load-application'"
exec --no-startup-id "i3-msg 'workspace 1; exec another-quick-to-load-application'"
exec --no-startup-id "i3-msg 'workspace 2; exec slow-to-load-application-1 && sleep 2'"
exec --no-startup-id "i3-msg 'workspace 3; exec yet-another-quick-to-load-application'"
exec --no-startup-id "i3-msg 'workspace 4; exec slow-to-load-application-2 && sleep 5'"
We may need to tweak the amount of time we need to wait for each application to open in the desired workspace.
We can use different features from i3 to have a specific application (or even specific windows) on a particular workspace. These two features are: assign and for_window + move. Both solutions will get all the instances of the applications into that workspace.
We’ll cover them now in detail, but the main difference between both is that i3 executes the first one when the application displays the windows on the screen, while i3 executes the second every time a window title changes.
Using application assignment on i3 is the recommended solution in most cases. With an application assignment, we are targeting window classes (and even window instances).
As a starting point to define an assignment, we need to add a line with the following syntax to the configuration file:
assign <criteria> [workspace number]
We need to define the criteria of the application we want to match. For that, we can use the following command with xprop and search the WM_CLASS of the given application with grep:
$ xprop | grep WM_CLASS
Our mouse cursor will become a crosshair, and we can click on the application that we want to match. The terminal will then return the class of the application:
$ xprop | grep CLASS
WM_CLASS(STRING) = "Navigator", "firefox"
The first part of the WM_CLASS is the instance name, and the second is the application class.
We can perform application assignments based on class or instance information. Let’s see some examples:
assign [class="firefox"] 1
assign [class="^firefox$"] 2
assign [class="^firefox$" instance="^Navigator$"] 3
The first line will match all the applications having firefox in their class name (for example, an application named firefox-debug will also be set into workspace 1).
The second line will perform an exact match and only get the applications whose class name exactly matches firefox for workspace 2.
The third line will match only those applications whose class name exactly matches firefox and the instance name Navigator for workspace 3.
We can add several assignments to our i3 configuration file to be processed in order. The first one that matches the pattern is taken, not considering the rest.
There are several more options to customize the assignment, such as assigning applications to a certain display or screen output.
For some applications, their name changes, so we can’t use the assign expression that we covered before.
For example, Spotify doesn’t set any class hint when displaying the window, so we cannot rely on the assign expression. But i3 has this covered as well!
In those scenarios, we need to request that i3 move the application to a workspace with the following syntax:
for_window [class="name"] move to workspace [workspace number]
We can get the class as we did previously with xprop and grep. For example, for Spotify, this line would look like:
for_window [class="spotify"] move to workspace 2
In the previous snippet, we request that all spotify instances be moved to workspace 2.
Since i3 version 4.8, there is a new layout saving feature. This feature is used to automate and streamline our desktop experience by immediately laying out some of our applications in a preferred way.
With layout saving and restoring, we can store the current layout in a JSON file. Then, we can restore this layout whenever we want. This can be useful, for example, if we use a specific layout when doing a task that requires several applications.
To save the current layout, we’ll use the i3-save-tree application. This will print the JSON representation of the current layout. We can pipe the output to a file so that we can modify it later:
$ i3-save-tree --workspace 2 > ~/.i3/workspace-2.json
With this expression, we’ve saved only workspace 2 into the JSON file.
Note that we need to edit the JSON file to customize the content and make it compatible with the loading mechanism.
We can then restore a layout that we’ve saved previously with exec and i3-msg as we did before:
exec --no-startup-id "i3-msg 'workspace 2; append_layout ~/.i3/workspace-2.json'"
This is something we can also link to a keyboard shortcut:
bindsym Mod4+a append_layout ~/.i3/workspace-2.json
We can use this to get a layout we repeatedly need with a couple of presses on our keyboard.
In this article, we talked about relating applications and workspaces in i3.
First, we discussed how to automatically get some applications in specific workspaces whenever we start our system.
Then, we used assignments to get certain applications to specific workspaces. There are two different ways to perform the assignment between application and workspace.
Finally, we considered layout saving and restoring to get the full layout with tiling and applications in a given location.