aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AGENTS.md63
-rw-r--r--CLAUDE.md6
-rw-r--r--LICENSE338
-rw-r--r--README.md55
-rwxr-xr-xbin/blackpearl-emoji.sh19
-rwxr-xr-xbin/blackpearl-sshmenu.sh40
-rwxr-xr-xbin/firefox-profile48
-rwxr-xr-xbin/notify-actions.sh41
-rwxr-xr-xbin/qar-scrotmenu.sh34
-rwxr-xr-xbin/rofipass351
-rwxr-xr-xbin/sd-webui86
-rwxr-xr-xbin/udt-launcher.sh22
-rwxr-xr-xbin/udt-powermenu.sh96
-rwxr-xr-xinstall.sh25
14 files changed, 1224 insertions, 0 deletions
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..4b44a10
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,63 @@
+# AGENTS.md
+
+Guidance for AI coding agents working in this repository.
+
+## What this is
+
+`rofi-scripts`: the shell scripts that open rofi menus on a Hyprland desktop.
+Plain bash or POSIX sh, one file per menu under `bin/`, no build step. Runtime
+deps are rofi 2.0 plus whatever each menu drives (pass, grimblast, notifyctl,
+sd-server, firefox).
+
+`./install.sh` symlinks every file in `bin/` into `~/bin/`, so edits are live
+on the next launch. The names are the ones hypr-theme's keybindings call
+(`udt-powermenu.sh`, `qar-scrotmenu.sh`, `blackpearl-sshmenu.sh`, ...), so a
+rename here must be matched there.
+
+## The themes live elsewhere
+
+Every script points rofi at a layout under `~/.config/rofi/udt/`, which the
+sibling `unified-desktop-theme` repo installs. This repo holds no `.rasi`.
+A layout change (header, card grid, banner) belongs there; here only the
+per-menu bits passed on the command line: `-p` title, `-mesg`,
+`-theme-str` overrides, keybindings.
+
+Menus on the searchable layouts (`list.rasi`, `grid.rasi`, `ssh.rasi`) show a
+wallpaper banner with the `-p` text as a title plate above the search bar.
+The house style for that title is a Nerd Font glyph, two spaces, a word and a
+colon: `'󰌋 Pass:'`. Pick glyphs from the `U+F0xxx` range; `ClearlyU` claims
+much of the older Private Use Area and draws a blank instead.
+`fc-match ":charset=f030b" family` says which font wins.
+
+## Gotchas
+
+- **One quoted string per `-theme-str`.** rofi 2.0's lexer reads from the
+ first `"` to the last, so `textbox { font: "A"; } entry { placeholder: "B"; }`
+ in one argument silently swallows the second block. Pass two `-theme-str`.
+- **Glyph-only elements need `children: [ element-text ]`** in their layout,
+ or the hidden icon slot pushes the glyph off centre.
+- Do not judge a menu by exit code: rofi exits non-zero on Escape.
+
+## Conventions
+
+- New menu: one file in `bin/`, license header, then `./install.sh`.
+- Placeholders only in code, docs and commits: no hostnames, account names or
+ home paths. A gitleaks hook enforces it.
+
+## Testing
+
+No test suite. `bash -n bin/<script>` (or `sh -n`) for syntax. For anything
+visual, open the menu in the session, screenshot and look:
+
+ grim -o DP-1 /tmp/shot.png
+
+`wtype -k Escape` closes it from a script.
+
+## Repo facts
+
+- License: GPLv2 only (`LICENSE`, header in each source file), except
+ `bin/rofipass` (derived from MIT-licensed upstream, notice kept in the file)
+ and `bin/udt-powermenu.sh`, `bin/udt-launcher.sh` (derived from adi1090x/rofi,
+ GPL-3.0 like upstream).
+- `origin` is the personal git server (cgit section "Linux").
+- Work directly on master.
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..0d86339
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,6 @@
+# CLAUDE.md
+
+This file is intentionally thin. AGENTS.md is the single source of truth for
+project guidance, shared across every agent tool. Edit AGENTS.md instead.
+
+@AGENTS.md
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..9efa6fb
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,338 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, see <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Moe Ghoul>, 1 April 1989
+ Moe Ghoul, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..4eae4d9
--- /dev/null
+++ b/README.md
@@ -0,0 +1,55 @@
+# rofi-scripts
+
+The scripts behind the rofi menus on my Hyprland desktop: power menu, app
+launcher, screenshot picker, SSH host cards, password store, emoji picker,
+Firefox profile picker, notification actions and a Stable Diffusion model
+picker. They are styled by the layouts from
+[unified-desktop-theme](https://git.danix.xyz/unified-desktop-theme/), which
+must be installed for them to look right.
+
+## Requirements
+
+- rofi 2.0
+- unified-desktop-theme's rofi layouts in `~/.config/rofi/udt/`
+- a Nerd Font (Inconsolata Nerd Font Mono) for the menu glyphs
+- per menu: `pass` (rofipass), `grimblast` (screenshots), `notifyctl`
+ (notification actions), `sd-server` (sd-webui), `hyprctl`, `jq`
+
+## Install
+
+ ./install.sh
+
+Symlinks every script in `bin/` into `~/bin/` (which must be on `PATH`),
+replacing any file of the same name. Bind them to keys in your window manager.
+
+## Scripts
+
+| Script | What it opens |
+| --- | --- |
+| `udt-powermenu.sh` | shutdown, reboot, sleep, logout, with a confirmation step |
+| `udt-launcher.sh` | application launcher |
+| `qar-scrotmenu.sh` | whole screen or area screenshot |
+| `blackpearl-sshmenu.sh` | hosts from `~/.ssh/config` as cards, opens `ssh` in a terminal |
+| `rofipass` | password store browser: copy, add, edit, delete, OTP |
+| `blackpearl-emoji.sh` | emoji picker |
+| `firefox-profile` | Firefox profile picker, one profile behind a password |
+| `notify-actions.sh` | pick one of a notification's actions |
+| `sd-webui` | pick a Stable Diffusion model, start sd-server, open its web UI |
+
+## License
+
+Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+
+GPLv2 only. See [LICENSE](LICENSE) for the full text. Exceptions, noted in
+each file: `rofipass` derives from
+[aocoronel/rofipass](https://github.com/aocoronel/rofipass) (MIT), and
+`udt-powermenu.sh` and `udt-launcher.sh` derive from
+[adi1090x/rofi](https://github.com/adi1090x/rofi) (GPL-3.0).
+
+## Development Approach
+
+This project is developed using AI-assisted tools. Code is generated with the help of AI based on human-provided specifications, design decisions, and iterative feedback.
+
+All contributions are reviewed, tested, and curated by the maintainer before being included in the codebase. AI is used as a productivity and exploration tool, while human oversight remains central to all decisions.
+
+The goal is to combine the flexibility of AI-assisted development with standard open-source practices such as transparency, review, and accountability.
diff --git a/bin/blackpearl-emoji.sh b/bin/blackpearl-emoji.sh
new file mode 100755
index 0000000..3969c43
--- /dev/null
+++ b/bin/blackpearl-emoji.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+# blackpearl-emoji.sh - emoji picker, rofi themed by udt
+# Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+rofi -no-lazy-grab -modi emoji -show emoji -display-emoji '󰞅 Emoji:' -theme ~/.config/rofi/udt/grid.rasi
+
diff --git a/bin/blackpearl-sshmenu.sh b/bin/blackpearl-sshmenu.sh
new file mode 100755
index 0000000..b0a0fc1
--- /dev/null
+++ b/bin/blackpearl-sshmenu.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# blackpearl-sshmenu.sh - the hosts in ~/.ssh/config as rofi cards
+# Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# rofi's own ssh mode shows the alias only, so the config is read here.
+# ponytail: plain "Keyword value" lines in ~/.ssh/config only; Include and
+# Match are not followed, wildcard Host patterns are skipped.
+mapfile -t hosts < <(awk '
+ function flush() { if (name != "") print name "\t" user "\t" addr }
+ tolower($1) == "host" { flush(); name = ($2 ~ /[*?]/) ? "" : $2; user = ""; addr = $2 }
+ tolower($1) == "hostname" { addr = $2 }
+ tolower($1) == "user" { user = $2 }
+ END { flush() }' ~/.ssh/config)
+
+# Two lines a card: the alias, then "user · address" with the user only where
+# the config sets one. Entries are joined on "|" so each can hold a newline.
+entries=()
+for h in "${hosts[@]}"; do
+ IFS=$'\t' read -r name user addr <<< "$h"
+ entries+=("<b>$name</b>
+<span size='small' fgalpha='65%'>${user:+$user · }$addr</span>")
+done
+
+i=$(IFS='|'; printf '%s' "${entries[*]}" | rofi -dmenu -i -markup-rows \
+ -sep '|' -eh 2 -format i -p '󰆍 SSH:' -theme ~/.config/rofi/udt/ssh.rasi) || exit
+name=${hosts[i]%%$'\t'*}
+exec rofi-sensible-terminal -e ssh "$name"
diff --git a/bin/firefox-profile b/bin/firefox-profile
new file mode 100755
index 0000000..3920e09
--- /dev/null
+++ b/bin/firefox-profile
@@ -0,0 +1,48 @@
+#!/bin/bash
+# firefox-profile - pick a Firefox profile with rofi, one behind a password
+# Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# Pick a Firefox profile with rofi; one profile requires a password.
+# Hash file: printf '%s' 'secret' | sha256sum | cut -d' ' -f1 > ~/.config/firefox-profile.hash
+# ponytail: wrapper gate only, `firefox -P <name>` bypasses it. Encrypt the profile dir if that matters.
+
+PROTECTED="danix"
+HASHFILE="$HOME/.config/firefox-profile.hash"
+INI="$HOME/.mozilla/firefox/profiles.ini"
+
+# Opening a link with exactly one profile running: hand it to that instance,
+# no picker. The protected profile was already unlocked to get it running.
+if [ $# -gt 0 ]; then
+ running=$(pgrep -af '^/usr/lib64/firefox/firefox(-bin)? (.* )?-P ' | sed -n 's/.* -P \([^ ]*\).*/\1/p' | sort -u)
+ [ -n "$running" ] && [ "$(wc -l <<<"$running")" -eq 1 ] && exec firefox -P "$running" "$@"
+fi
+
+profile=$(sed -n 's/^Name=//p' "$INI" | rofi -dmenu -theme ~/.config/rofi/udt/list.rasi -i -p '󰈹 Firefox:') || exit 0
+[ -n "$profile" ] || exit 0
+
+if [ "$profile" = "$PROTECTED" ]; then
+ pass=$(rofi -dmenu -theme ~/.config/rofi/udt/list.rasi -password -l 0 \
+ -mesg "Unlock Firefox profile: $profile" \
+ -theme-str 'mainbox { children: [ message, inputbar ]; padding: 16px; spacing: 8px; } message { background-color: transparent; padding: 0 0 4px 2px; } textbox { font: "Noto Sans Bold 13"; }' \
+ -theme-str 'entry { placeholder: "Password"; }' </dev/null) || exit 0
+ hash=$(printf '%s' "$pass" | sha256sum | cut -d' ' -f1)
+ if [ "$hash" != "$(cat "$HASHFILE" 2>/dev/null)" ]; then
+ notify-send "Firefox" "Wrong password" 2>/dev/null
+ exit 1
+ fi
+fi
+
+exec firefox -P "$profile" "$@"
diff --git a/bin/notify-actions.sh b/bin/notify-actions.sh
new file mode 100755
index 0000000..0c49c6b
--- /dev/null
+++ b/bin/notify-actions.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+#
+# Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# Pick one of a notification's actions with rofi and invoke it. The renderer
+# passes the labels and keys as arguments, so nothing here parses JSON.
+#
+# notify-actions.sh <id> <label> <key> [label key ...]
+
+set -u
+
+[[ $# -ge 3 ]] || { echo "usage: ${0##*/} <id> <label> <key> ..." >&2; exit 2; }
+
+id="$1"; shift
+labels=()
+keys=()
+while [[ $# -ge 2 ]]; do
+ labels+=("$1")
+ keys+=("$2")
+ shift 2
+done
+
+choice="$(printf '%s\n' "${labels[@]}" | rofi -dmenu -i -p "Notification" \
+ -theme "$HOME/.config/rofi/udt/menu.rasi")"
+[[ -n "$choice" ]] || exit 0
+
+for i in "${!labels[@]}"; do
+ if [[ "${labels[$i]}" == "$choice" ]]; then
+ notifyctl action "$id" "${keys[$i]}"
+ exit $?
+ fi
+done
diff --git a/bin/qar-scrotmenu.sh b/bin/qar-scrotmenu.sh
new file mode 100755
index 0000000..2b7341f
--- /dev/null
+++ b/bin/qar-scrotmenu.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# qar-scrotmenu.sh - screenshot menu, rofi themed by udt
+# Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+rofi_command=(rofi -theme ~/.config/rofi/udt/screenshot.rasi)
+
+### Options ###
+screen=""
+area=""
+# Variable passed to rofi
+options="$screen\n$area"
+
+chosen="$(echo -e "$options" | "${rofi_command[@]}" -dmenu -selected-row 1 -p '󰄀 Screenshot:')"
+case $chosen in
+ $screen)
+ grimblast -w 3 -n -t png copysave active
+ ;;
+ $area)
+ grimblast -n -t png copysave area
+ ;;
+esac
diff --git a/bin/rofipass b/bin/rofipass
new file mode 100755
index 0000000..b9620f8
--- /dev/null
+++ b/bin/rofipass
@@ -0,0 +1,351 @@
+#!/usr/bin/env sh
+# rofipass - rofi front end for pass
+#
+# Derived from rofipass by Augusto Coronel (https://github.com/aocoronel/rofipass),
+# released under the MIT License, whose notice is kept below as it requires.
+# Modifications Copyright (C) 2026 Danilo M. <danix@danix.xyz>, released under
+# the GNU General Public License version 2 (see LICENSE).
+#
+# MIT License
+#
+# Copyright (c) 2025 Augusto Coronel
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+### Colors
+
+help_color="#7c5cff"
+div_color="#334433"
+label="#f067fc"
+
+###
+
+### Bindings
+
+kb_copy_email="Ctrl+2" # EMAIL
+kb_copy_otp="Ctrl-1" # COPY TOTP
+kb_add_pass="Ctrl+r" # PASSWORD
+kb_add_otp="Ctrl+t" # ADD TOTP
+kb_delete="Ctrl-x" # DELETE
+kb_edit="Ctrl+y" # EDIT
+kb_close_tomb="Ctrl-z" # CLOSE TOMB
+kb_open_tomb="Ctrl-o" # OPEN TOMB
+
+###
+
+clipmethod="$XDG_SESSION_TYPE"
+passdir=${PASSWORD_STORE_DIR:-$HOME/.password-store}
+
+COLOR_YELLOW="$(tput setaf 226)"
+COLOR_RED="$(tput setaf 196)"
+COLOR_GREEN="$(tput setaf 82)"
+COLOR_BLUE="$(tput setaf 87)"
+COLOR_RESET=$(tput sgr0)
+
+printfc() {
+ mode=$1
+ case $mode in
+ "ERROR" | "FATAL")
+ color="$COLOR_RED"
+ ;;
+ "WARN")
+ mode="WARNING"
+ color="$COLOR_YELLOW"
+ ;;
+ "DEBUG")
+ color="$COLOR_BLUE"
+ ;;
+ "INFO")
+ color="$COLOR_GREEN"
+ ;;
+ esac
+ text=$2
+ printf "%s[%s]:%s %s\n" "${color}" "${mode}" "${COLOR_RESET}" "${text}"
+}
+
+check_command() {
+ for cmd in "$@"; do
+ if ! command -v "$cmd" >/dev/null 2>&1; then
+ printfc FATAL "$cmd is not installed."
+ return 1
+ fi
+ done
+}
+
+_notify() {
+ message="$1"
+ header="rofipass"
+ urgency="$2"
+ time=${3:-$time}
+ echo "$message"
+ if [ "$time" -eq 0 ]; then
+ notify-send -u "$urgency" "$header" "$message"
+ else
+ notify-send -u "$urgency" "$header" "$message" --expire-time="$time"000 --wait
+ fi
+}
+
+die() {
+ mode=$1
+ message=$2
+ urgency=$3
+
+ printfc "$mode" "$message"
+ _notify "$message" "$urgency"
+ exit 1
+}
+
+version() {
+ echo "v1.1.0"
+}
+
+usage() {
+ cat <<EOF
+rofipass | A rofi extension for pass
+
+Usage: rofipass [OPTIONS] <COMMAND>
+
+Options:
+ -e <EDITOR> Set editor
+ -f Lift swap restrictions (for tomb)
+ -h Display this help message and exit
+ -l <LENGTH> Default password length on generation
+ -t <TERM> Default terminal emulator (for tomb)
+ -v Display the current version number
+ -T <SECONDS> Clearing time
+
+Example:
+ rofipass -f -l 72 -t kitty -e nvim -T 10
+EOF
+}
+
+_rofi() {
+ rofi -dmenu -theme ~/.config/rofi/udt/list.rasi -i -no-levenshtein-sort "$@"
+}
+
+copy_email() {
+ email=$(pass "$menu" | sed -n 's/^email=//p')
+ case "$clipmethod" in
+ "x11")
+ xclip "$email" || die FATAL "failed to copy the email." "critical"
+ _notify "Copied to clipboard. Clearing in $time seconds" "normal"
+ ;;
+ "wayland")
+ wl-copy "$email" || die FATAL "failed to copy the email." "critical"
+ _notify "Copied to clipboard. Clearing in $time seconds" "normal"
+ ;;
+ esac
+ # clearboard
+}
+
+append_otp() {
+ check_command zbarimg || die FATAL "zbarimg is not installed." "critical"
+ case "$clipmethod" in
+ "x11")
+ xclip -o | zbarimg -q --raw - | pass otp append "$menu" || die FATAL "failed to append OTP to $menu" "critical"
+ _notify "Inserted OTP successfully to $menu" "normal"
+ ;;
+ "wayland")
+ wl-paste --type image/png | zbarimg -q --raw - | pass otp append "$menu" || die FATAL "failed to append OTP to $menu" "critical"
+ _notify "Inserted OTP successfully to $menu" "normal"
+ ;;
+ esac
+}
+
+clearboard() {
+ [ -x "$(command -v notifyctl)" ] && notifyctl close-all
+
+ case "$clipmethod" in
+ "x11")
+ echo "" | xclip -sel clip
+ ;;
+ "wayland")
+ [ -x "$(command -v cliphist)" ] && cliphist wipe
+ echo "" | wl-copy
+ ;;
+ esac
+}
+
+tomb_open() {
+ if [ -n "$FORCE" ]; then
+ $term -e sh -c "pass open -f"
+ else
+ $term -e sh -c "pass open"
+ fi
+}
+
+tomb_close() {
+ $term -e sh -c "pass close"
+ pass_val=$?
+ if [ "$pass_val" -ne 0 ]; then
+ die FATAL "failed to close tomb." -u "critical"
+ else
+ _notify "Your password tomb has been closed!" "normal" 0
+ fi
+}
+
+deleteMenu() {
+ delask=$(printf "1. Yes\n2. No" | _rofi -p '󰆴 Delete:' -mesg "<span color='${label}'>Really delete</span> <span color='${help_color}'>$menu?</span>")
+ val=$?
+ [ $val -eq 1 ] && {
+ _notify "Cancelled!" "low" 0
+ main
+ }
+ [ "$delask" = "1. Yes" ] && pass rm -f "$menu" && _notify "Deleted $menu" "normal" 0
+ main
+}
+
+add_password() {
+ length=${length:-72}
+ addmenu=$(
+ echo | _rofi -p '󰐕 New password:' -lines 0 \
+ -theme-str 'window { width: 25em; } listview { lines: 0; } entry { placeholder: "Enter password name"; }'
+ )
+ val=$?
+ if [ $val -eq 1 ]; then
+ _notify "Cancelled!" "low" 0
+ main
+ elif [ $val -eq 0 ]; then
+ if command -v "passgen.py" >/dev/null 2>&1; then
+ passgen.py 3 | pass insert -e "$addmenu"
+ else
+ pass generate "$addmenu" "$length"
+ fi
+ if [ $val -eq 1 ]; then
+ _notify ERROR "failed to add password" 0
+ main
+ else
+ _notify "Added $addmenu" "normal" 0
+ fi
+ fi
+ main
+}
+
+edit_password() {
+ $term -e sh -c "export EDITOR=\"$editor\"; pass edit \"$menu\""
+}
+
+main() {
+ enable_tomb=0
+ enable_otp=0
+ enable_zbar=0
+
+ if ! command -v "tomb" >/dev/null 2>&1; then
+ enable_tomb=1
+ fi
+ if ! command -v "zbarimg" >/dev/null 2>&1; then
+ enable_zbar=1
+ fi
+
+ pass otp -h >/dev/null 2>&1 || enable_otp=1
+
+ HELP=""
+
+ HELP="$HELP<span color='${label}'>Actions: </span><span color='${help_color}'>${kb_add_pass}</span>: Add <span color='${div_color}'>|</span> <span color='${help_color}'>${kb_delete}</span>: Delete <span color='${div_color}'>|</span> <span color='${help_color}'>${kb_edit}</span>: Edit"
+
+ if [ "$enable_zbar" -eq 0 ]; then
+ ZBAR_HELP=" <span color='${div_color}'>|</span> <span color='${help_color}'>${kb_add_otp}</span>: Add OTP"
+ HELP="$HELP$ZBAR_HELP"
+ fi
+
+ HELP="$HELP
+<span color='${label}'>Copy: </span><span color='${help_color}'>Enter</span>: Copy Password <span color='${div_color}'>|</span> <span color='${help_color}'>${kb_copy_email}</span>: Copy Email"
+
+ if [ "$enable_otp" -eq 0 ]; then
+ OTP_HELP=" <span color='${div_color}'>|</span> <span color='${help_color}'>${kb_copy_otp}</span>: Copy OTP"
+ HELP="$HELP$OTP_HELP"
+ fi
+
+ if [ "$enable_tomb" -eq 0 ]; then
+ TOMB_HELP="<span color='${label}'>Tomb: </span><span color='${help_color}'>${kb_close_tomb}</span>: Close Tomb <span color='${div_color}'>|</span> <span color='${help_color}'>${kb_open_tomb}</span>: Open Tomb"
+ HELP="$HELP
+$TOMB_HELP"
+ fi
+
+ pass=$(find -L "$passdir" -type f -name '*.gpg' -printf '%P\n' | sed 's/\.gpg//')
+ menu=$(echo "${pass}" | _rofi -p '󰌋 Pass:' -mesg "${HELP}" -kb-custom-1 "${kb_add_pass}" -kb-custom-2 "${kb_copy_otp}" -kb-custom-3 "${kb_delete}" -kb-custom-4 "${kb_edit}" -kb-custom-5 "${kb_close_tomb}" -kb-custom-6 "${kb_open_tomb}" -kb-custom-7 "${kb_copy_email}" -kb-custom-8 "${kb_add_otp}")
+
+ val=$?
+ case "$val" in
+ 1) exit ;;
+ 12) deleteMenu ;;
+ 11) # OTP Copy
+ [ "$enable_otp" -eq 0 ] && {
+ timeout 3 pass otp -c "$menu" || die ERROR "failed to copy OTP!" "normal"
+ _notify "Copied to clipboard. Clearing in $time seconds" "normal"
+ # clearboard
+ }
+ ;;
+ 10) add_password ;;
+ 13) edit_password ;;
+ 14) [ "$enable_tomb" -eq 0 ] && tomb_close ;;
+ 15) [ "$enable_tomb" -eq 0 ] && tomb_open ;;
+ 16) copy_email ;;
+ 17) [ "$enable_zbar" -eq 0 ] && append_otp ;;
+ 0)
+ pass -c "$menu" || die ERROR "failed to copy the password!" "normal"
+ _notify "Copied to clipboard. Clearing in $time seconds" "normal"
+ # clearboard
+ ;;
+ esac
+}
+
+while getopts ":hvfl:t:T:e:" opt; do
+ case "$opt" in
+ h)
+ usage
+ exit 0
+ ;;
+ e)
+ editor="$OPTARG"
+ ;;
+ v)
+ version
+ exit 0
+ ;;
+ f)
+ FORCE=true
+ ;;
+ l)
+ length="$OPTARG"
+ ;;
+ t)
+ term="$OPTARG"
+ ;;
+ T)
+ time="$OPTARG"
+ ;;
+ ?)
+ printfc FATAL "invalid option '-$OPTARG'" >&2
+ exit 1
+ ;;
+ esac
+done
+
+shift $((OPTIND - 1))
+
+check_command rofi pass || exit 1
+
+[ ! -d "$passdir" ] && die FATAL "no password directory found!" "low"
+
+[ -z "$editor" ] && editor=${EDITOR:-nano}
+term=${term:-kitty}
+time=${time:-5}
+
+main
diff --git a/bin/sd-webui b/bin/sd-webui
new file mode 100755
index 0000000..0d72547
--- /dev/null
+++ b/bin/sd-webui
@@ -0,0 +1,86 @@
+#!/bin/bash
+# sd-webui - start sd-server with a model picked from rofi
+# Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# Start sd-server (stable-diffusion.cpp) with a model picked from rofi and open its web UI.
+# Runs in the foreground: close the terminal (or Ctrl-C) to stop it and free VRAM.
+
+M=/data/LLM-models/SD
+QWEN=(--llm $M/Qwen3VL-8B-Instruct-Q8_0.gguf
+ --llm_vision $M/mmproj-Qwen3VL-8B-Instruct-F16.gguf
+ --vae $M/vae/qwen_image_2.1_vae_bf16.safetensors)
+SDXL=(--cfg-scale 7.0 --steps 25) # same defaults as imggen
+
+# Pick the model (sd-server loads one per process, so choose at start).
+case $(printf '%s\n' \
+ "Qwen Image 2.1 (base, 20 steps, text/edit/RGBA)" \
+ "Qwen Image 2.1 turbo (6 steps)" \
+ "Z-Image Turbo (8 steps, photoreal)" \
+ "FLUX.2 klein 4B (4 steps, edit)" \
+ "Krea 2 Turbo (8 steps, photoreal)" \
+ "Wan2.2 TI2V 5B (video, text/image)" \
+ "SDXL base" \
+ "RealVisXL V5" \
+ "Pony Diffusion V6 XL" \
+ | rofi -dmenu -i -theme ~/.config/rofi/udt/list.rasi -p '󰋩 SD model:' \
+ -theme-str 'entry { placeholder: "Search models"; }') in
+ "Qwen Image 2.1 (base"*) MODEL=(--diffusion-model $M/qwen_image_2.1-Q8_0.gguf "${QWEN[@]}"
+ --cfg-scale 6.0 --cache-mode cache-dit) ;;
+ "Qwen Image 2.1 turbo"*) MODEL=(--diffusion-model $M/Qwen-Image-2.1-viggle-turbo-v0.3-6step-Q8_0.gguf "${QWEN[@]}"
+ --cfg-scale 1.0 --steps 6) ;;
+ Z-Image*) MODEL=(--diffusion-model $M/z_image_turbo-Q8_0.gguf
+ --llm $M/Qwen3-4B-Instruct-2507-Q8_0.gguf --vae $M/vae/flux1-ae.safetensors
+ --cfg-scale 1.0 --steps 8 --diffusion-fa) ;;
+ FLUX.2*) MODEL=(--diffusion-model $M/flux-2-klein-4b-Q8_0.gguf
+ --llm $M/Qwen3-4B-Q8_0.gguf --vae $M/vae/flux2-vae.safetensors
+ --cfg-scale 1.0 --steps 4 --diffusion-fa) ;;
+ # Q6_K: same output as Q8_0 at seed 42, ~20% faster (both still offload on 12G).
+ Krea*) MODEL=(--diffusion-model $M/Krea-2-Turbo-Q6_K.gguf
+ --llm $M/Qwen3VL-4B-Instruct-Q8_0.gguf --vae $M/vae/wan_2.1_vae.safetensors
+ --cfg-scale 1.0 --steps 8 --diffusion-fa) ;;
+ # 1280x704 is the model's native 720p. Frames must be 4k+1 at 24 fps: 49 = 2 s, 121 = 5 s.
+ # Settings follow upstream Wan2.2 5B defaults (cfg 5, shift 5); drop to 832x480 if too slow.
+ Wan2.2*) MODEL=(--diffusion-model $M/Wan2.2-TI2V-5B-Q8_0.gguf
+ --t5xxl $M/umt5-xxl-encoder-Q8_0.gguf --vae $M/vae/wan2.2_vae.safetensors
+ --cfg-scale 5.0 --steps 30 --flow-shift 5.0 --diffusion-fa
+ -W 1280 -H 704 --video-frames 49 --temporal-tiling) ;;
+ # imggen's diffusers weights, symlinked into the layout sd.cpp loads as a directory
+ "SDXL base") MODEL=(-m $M/sdxl-links/sdxl "${SDXL[@]}") ;;
+ RealVisXL*) MODEL=(-m $M/sdxl-links/realvis "${SDXL[@]}") ;;
+ Pony*) MODEL=(-m $M/sdxl-links/pony "${SDXL[@]}" --clip-skip 2) ;;
+ *) exit 0 ;;
+esac
+
+PORT=${PORT:-7860}
+URL=http://127.0.0.1:$PORT/
+
+# Open the browser once the server answers (model loading takes a while).
+(
+ until curl -sf -o /dev/null "$URL"; do sleep 1; done
+ notify-send -a sd-server -i applications-graphics "Stable Diffusion server started" "$URL"
+ xdg-open "$URL" >/dev/null 2>&1
+) &
+trap 'kill $! 2>/dev/null' EXIT
+
+# Log to a file too: the terminal loses the output when the server crashes.
+# stdbuf -oL: line-buffer stdout so the last lines before a crash reach the log.
+LOG=${XDG_CACHE_HOME:-$HOME/.cache}/sd-server.log
+# MODEL goes after the shared defaults so a model can override them (e.g. Wan's -W/-H).
+stdbuf -oL -eL sd-server --listen-port "$PORT" \
+ --lora-model-dir $M/loras \
+ --sampling-method euler -W 1024 -H 1024 --seed -1 \
+ "${MODEL[@]}" \
+ --offload-to-cpu -v "$@" 2>&1 | tee "$LOG"
diff --git a/bin/udt-launcher.sh b/bin/udt-launcher.sh
new file mode 100755
index 0000000..d0a8013
--- /dev/null
+++ b/bin/udt-launcher.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+## Author : Aditya Shakya (adi1090x)
+## Github : @adi1090x
+## Derived from adi1090x/rofi, GPL-3.0 like upstream. Modifications
+## Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+#
+## Rofi : Launcher (Modi Drun, Run, File Browser, Window)
+#
+## Available Styles
+#
+## style-1 style-2 style-3 style-4 style-5
+## style-6 style-7 style-8 style-9 style-10
+## style-11 style-12 style-13 style-14 style-15
+
+dir="$HOME/.config/rofi/udt"
+theme='launcher'
+
+## Run
+rofi \
+ -show drun \
+ -theme ${dir}/${theme}.rasi
diff --git a/bin/udt-powermenu.sh b/bin/udt-powermenu.sh
new file mode 100755
index 0000000..6d8fb84
--- /dev/null
+++ b/bin/udt-powermenu.sh
@@ -0,0 +1,96 @@
+#!/usr/bin/env bash
+
+## Author : Aditya Shakya (adi1090x)
+## Github : @adi1090x
+## Derived from adi1090x/rofi, GPL-3.0 like upstream. Modifications
+## Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+#
+## Rofi : Power Menu
+#
+## Available Styles
+#
+## style-1 style-2 style-3 style-4 style-5
+
+# Current Theme
+dir="$HOME/.config/rofi/udt"
+theme='powermenu'
+
+# CMDs
+uptime="`uptime -p | sed -e 's/up //g'`"
+host=`hostname`
+
+# Options
+shutdown=''
+reboot=''
+logout=''
+sleep='󰤄'
+yes='󰗠'
+no='󰅙'
+
+# Rofi CMD
+rofi_cmd() {
+ rofi -dmenu \
+ -p "'ndi vidimu ${USER}" \
+ -mesg "Uptime: $uptime" \
+ -theme ${dir}/${theme}.rasi
+}
+
+# Confirmation CMD
+confirm_cmd() {
+ rofi -dmenu \
+ -p 'Confirmation' \
+ -selected-row 1 \
+ -mesg 'Simu Sicuri?' \
+ -theme "$HOME/.config/rofi/udt/confirm.rasi"
+}
+
+# Ask for confirmation
+confirm_exit() {
+ echo -e "$yes\n$no" | confirm_cmd
+}
+
+# Pass variables to rofi dmenu
+run_rofi() {
+ echo -e "$shutdown\n$reboot\n$sleep\n$logout" | rofi_cmd
+}
+
+# Execute Command
+run_cmd() {
+ selected="$(confirm_exit)"
+ if [[ "$selected" == "$yes" ]]; then
+ if [[ $1 == '--shutdown' ]]; then
+ notify-send 'system shutdown' 'the system is going to shutdown now'
+ sleep 1
+ /usr/bin/loginctl poweroff
+ elif [[ $1 == '--reboot' ]]; then
+ notify-send 'system reboot' 'the system is going to reboot now'
+ sleep 1
+ /usr/bin/loginctl reboot
+ elif [[ $1 == '--sleep' ]]; then
+ notify-send 'suspend to ram' 'the system is going to sleep now'
+ sleep 1
+ /usr/bin/loginctl suspend
+ elif [[ $1 == '--logout' ]]; then
+ hyprctl dispatch 'hl.dsp.exit()'
+ fi
+ else
+ exit 0
+ fi
+}
+
+# Actions
+chosen="$(run_rofi)"
+case ${chosen} in
+ $shutdown)
+ run_cmd --shutdown
+ ;;
+ $reboot)
+ run_cmd --reboot
+ ;;
+ $sleep)
+ run_cmd --sleep
+ ;;
+ $logout)
+ run_cmd --logout
+ ;;
+esac
diff --git a/install.sh b/install.sh
new file mode 100755
index 0000000..e9add5b
--- /dev/null
+++ b/install.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# install.sh - symlink the rofi scripts into ~/bin
+# Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# Links, not copies, so an edit here is live on the next launch. A file of
+# the same name already in ~/bin is replaced by the link.
+repo="$(cd "$(dirname "$0")" && pwd)"
+mkdir -p "$HOME/bin"
+for f in "$repo"/bin/*; do
+ ln -sfn "$f" "$HOME/bin/${f##*/}"
+ echo "linked ~/bin/${f##*/}"
+done