You describe a workspace as a tree of splits. Run dashboard and the workspace
becomes that. Run it again on a workspace that is already half-right and it
changes as little as it can — panes already in the right place are left running
and untouched.
h[
v[
h[ cava shell ]:2
lyrics
]:3
claude:3
v[ lavat pipes.sh ]
]
On an empty workspace, panes open one at a time and split each other, so you watch the layout assemble itself.
On a workspace that already has windows, it does as little as possible:
- windows already in the right place are left alone — not moved, not reopened, and never floated;
- a boundary that has drifted is nudged back;
- missing panes are opened and tiled into the gap they belong in.
Windows are identified by what is actually running inside them, so the
terminal you typed dashboard into becomes the layout's shell pane rather
than something to be closed. Anything that does have to go — a window not in the
layout, or an arrangement that cannot be reshaped without reopening — is listed
and asked about first.
git clone https://github.com/mgtaco/hypr-dashboard
cd hypr-dashboard
install -Dm755 dashboard ~/.local/bin/dashboard
install -Dm644 layouts.conf.example ~/.config/dashboard/layouts.confSingle file, standard library only. Needs hyprctl, ps, setsid, and a
terminal (kitty by default).
~/.config/dashboard/layouts.conf:
| Syntax | Meaning |
|---|---|
h[ a b c ] |
a, b, c side by side, left to right |
v[ a b ] |
a above b |
cava |
a pane running cava |
shell |
a pane that is just a shell prompt |
cava:3 |
given 3 shares of the space its parent hands out |
lavat {-o font_size=5} |
extra flags for this one pane's terminal |
"btop -p 0" |
quote a command containing spaces |
Sizes are relative to whatever sits beside them and default to 1. A group counts
as one thing too, so v[ cava:3 peaclock:2 ]:3 claims 3 shares from its own
parent and divides them 3:2 inside. Groups nest as deep as you like.
dashboard the default layout, on the current workspace
dashboard ambient a different layout from the config
dashboard --list which layouts exist
dashboard --delay 1.5 slower reveal when opening panes
dashboard --yes don't ask before closing windows
dashboard --rebuild close everything and build from scratch
dashboard --workspace 4 act on another workspace
dashboard --verbose explain what it decides to do
Pane order is not configurable, by design. Hyprland's dwindle layout does
not store "window X sits at position Y" — it stores a series of cuts, and every
new window splits an existing one in half. The order windows open in therefore
is the layout. The tree you write is the tree dwindle builds, so the script
just walks it top-down.
dwindle cannot re-nest. A new window only ever splits a single window, never a group. So a pane whose target space is currently shared by two or more windows cannot be slotted back in, and the script will ask to close and rebuild that part instead. This is a limitation of the layout engine, not the script.
Windows are never floated, not even briefly. Floating adopted windows to re-insert them is the obvious implementation and it looks terrible — you can see the layout churn between the start and end states. Everything is done in place.
- Hyprland 0.56 or newer. The script drives the compositor through
hyprctl repland thehl.dsp.*Lua dispatchers; 0.56 moved to the Lua config parser andhyprctl keyword/setpropno longer work. dwindlelayout.masterstores a different structure entirely.- Python 3, standard library only.
fishis currently hardcoded as the shell panes are launched under.
Pane names are just commands, so a layout only needs whatever it names. The
example config uses cava, lavat and pipes.sh, plus lyrics — that one is
terminal-lyrics
(crates.io), synced lyrics in the
terminal. Swap any of them for something you have.
MIT — see LICENSE.