r/i3wm • u/masterpiece_911 i3-gaps • 20d ago
OC I created a tool that recreates an i3/sway desktop from a declarative layout file
https://www.github.com/masterpiece911/layouterSo I use i3 / sway daily on my work machines, and find myself spending every morning just recreating my setup. This includes launching all my apps, launching my terminals, and arranging them just right. Of course, all of this dependent on what display hardware I have in front of me.
Since one of my habits is to reduce tasks that take 5 minutes to 5 seconds, I now wrote "layouter".
It takes a declarative TOML file and recreates the described workflow in your i3/sway session. If you already have windows running that layouter created before, it will only create what is missing. It supports display selection, floating windows, and nested containers. You can also create a kitty terminal layout to exactly your liking, including the layout of your choice. As with other i3 windows, running the same layout again will only create kitty panes that are missing currently.
You can pass arguments to your layout file, and the TOML will receive them. In a frontend project, you could as an example specify what microfrontend to set up your development environment for.
If you want to do more fancy stuff, like adapt your layout to whatever hardware you're currently running on, layouter also supports React JSX syntax. Use `useScreen` to adapt your layout to screen dimensions or more. Do more with your layout arguments. Do it all declaratively.
I'm interested in your opinions. I'm new to this community, but have been using i3 basically since I started using Linux. I'm curious if this will be of interest to anybody else. I tried i3 itself to save layouts, but having to start the apps myself afterwards kind of bummed me out. This is my answer to that limitation.
Have a good day!
1
u/badadhd 19d ago
Interested. Is it similar to the good old i3 resurrect? But with javascript?
1
u/masterpiece_911 i3-gaps 19d ago
I wasn’t aware of i3-resurrect, truth be told 😅. But that seems to be using a combination of i3’s layout loading functionality paired with IPC magic, whereas Layouter uses IPC exclusively and thus will work on sway as well.
The JavaScript is my genuine novel idea I guess, which allows you to reactively build your layout based on hardware setup. I frequently switch between home office and office work, with wildly different topology, and am a fronted developer myself, so using react syntax for this seemed like my way to go (everything is a nail if you’re used to working with hammers 😇).
1
u/masterpiece_911 i3-gaps 19d ago
Oh and being able to layout your terminal is the other novel idea 😉
1
u/desquared 19d ago
I am very interested in this. I too need to have all my windows and such juuuuust right. I usually make this work by never ever logging out but this may be what I am looking for.
1
u/masterpiece_911 i3-gaps 19d ago
Interested in your experience! Let me know how it goes.
1
u/desquared 19d ago
I spent over an hour trying to get this to work and gave up and uninstalled.
It took a bit to find the --capture option, which seemed like exactly what I want -- I put my windows where I want them, capture the state, and then whenever I want to restore that exact state, just run "layouter". That's what I expected.
But always what happened was either it couldn't find the existing window -- or, it couldn't launch a new program when it wasn't running.
It could never find Firefox, even when there exactly one window and the
matchmatched the app_id exactly. It would instead launch Firefox with a completely new, blank profile -- it didn't even use my existing profile.I then tried to start from scratch, working from the examples given in the documentation. But that never ever worked either. It could never, ever find Firefox, even with a title regex that should have worked (
.*Mozilla Firefox.*). It never could find my emacs window.I really, really want something like this. It seems like it would be perfect for me at work -- I'm a college professor, and want my desktop to be one way in my office; another when I'm in class presenting; and another when I have my laptop (and no external monitor) and am in a meeting or such.
The project seems like it ought to work in general, but my impression is that it in practice it's only good for your own particular setup, with kitty and your other dev tools.
Sorry. Uninstalled.
1
u/masterpiece_911 i3-gaps 17d ago
I’m sorry to hear that. My personal experience with Firefox was to disable restoring of the old sessions and to use the —new-window flag as a parameter to it. Don’t have experience with emacs to aid you there.
1
u/masterpiece_911 i3-gaps 15d ago
https://reddit.com/link/pcsvqaw/video/e99dusa35hsh1/player
Just to show you a minimal firefox setup. This works even if firefox is running already.
1
u/yurikhan 18d ago
What is your solution to Firefox? Specifically, when it restores the session and opens a dozen windows, how do you decide which window belongs to which slot in the layout?
I ended up coding a Firefox extension and a messaging host to let each Firefox window remember which workspace it last inhabited.
(Also I reject your premise of recreating window setup every morning. I just keep everything running, suspend my machine, wake it up next day. But 5 minutes per reboot is annoying enough.)
1
u/masterpiece_911 i3-gaps 17d ago
I disabled session restore with Firefox and invoke it with —new-window, haven’t had a problem. But I’m also using zen-browser.app, which is a Firefox derivative.
1
u/masterpiece_911 i3-gaps 15d ago
https://reddit.com/link/pcsvvaf/video/hmme7xr85hsh1/player
This would be my minimal firefox example 😄 .
1
u/yurikhan 15d ago
Hey, I get tab minimalism if it’s your entertainment machine. One tab at a time. But for real work? calendar, issue tracker kanban board, project chat, current issue, linked issues, design document, figma, thirdparty libraries reference, language reference, tools reference, other peoples’ MRs you are reviewing?
1
u/masterpiece_911 i3-gaps 15d ago
absolutely. I'm not enough into firefox to remember how it treats resuming your browsing. Personally, I use zen-browser which restores my tabs anyway, regardless of the 'restore session' setting, but it just doesn't open all the windows I had open last time. This fully scratches my itch.
And I fully intend on layouter to be my workhorse, totally with you there.
1
u/masterpiece_911 i3-gaps 15d ago edited 15d ago
I'm guessing I should require a similar extension to the one you have, which would mark individual windows with more than just an integer. If it is deterministic, that should enable layouter to identify individual windows, and place them according to your liking.
Personally, I'll stick to zen-browser. EDIT: but I'm working on a first-class firefox window primitive now.
1
u/yurikhan 15d ago
I briefly entertained the idea to record not only the workspace name but also path through marked containers, but that would require the restore workflow to create those marked containers if missing and set their layouts and split percentages and whatevermore else. So I chose to endure a single “mod+ctrl+right” per workspace per reboot to restore the
(splith (tabbed (…)) (tabbed (…)))layout.1
u/masterpiece_911 i3-gaps 14d ago edited 14d ago
Layouter v1.1.0 now has a Firefox Companion extension which tracks any window created with the newly added FirefoxWindow and FirefoxTab primitive. Also see the announcement.
2
u/pdoherty926 20d ago
I just gave this a try and it's quite neat. Nice work! I much prefer this to the imperative approach preferred by i3.
Sadly, the version of Kitty in the Debian repos is missing some features and breaks with: "Unknown option: --next-to". I don't particularly like Kitty (for organizational reasons) and use Ghostty, so this isn't a deal-breaker for me. I am curious to know if you have any thoughts about other terminal targets, though.
Otherwise, I generally use tmuxinator/rmuxinator (my project) for intra-workspace config. I'm going to have a poke and see how these might be used together. rmuxinator can be used as a library, so you could conceivably use one of the Python-Rust bridges to call it from layouter or, more crudely, just shell out to it. I'm envisioning a scenario where I have my i3 config do the bare minimum to setup keybindings and whatnot and then launch layouter to setup the broad strokes of my desired workspaces and then run rmuxinator inside each one of them to configure tmux and launch other programs.