Compare commits

..
27 Commits
Author SHA1 Message Date
SirBlob 5c7f8911ec Update wallpaper gallery for 9 new wallpapers 2026-08-01 22:30:19 -04:00
SirBlob 4eb3b23d4b Add 9 new wallpapers 2026-08-01 22:28:33 -04:00
SirBlob 45a60030d1 Fix Zen browser colors to follow active theme, not pywal cache
zen/userChrome.css read straight from ~/.cache/wal/colors.css, which
only updates on wallpaper pick and ignores static/shared theme
changes. Now generates zen.css from colors.toml via Omarchy's own
templating, same as waybar/alacritty/etc.
2026-08-01 20:09:39 -04:00
SirBlob 3266666ade Add 5 new wallpapers, update gallery 2026-08-01 15:02:15 -04:00
SirBlob acc96492ee Add theme system: local themes, picker, static/dynamic mode
- blob_theme: apply local or shared themes, --dynamic recolors from
  the current wallpaper without changing it, --print saves the active
  theme's colors.toml (e.g. for a dynamic palette worth keeping)
- themes/: drop-in colors.toml files that install.sh syncs into
  Omarchy's theme dir, alongside any already-installed themes
- ThemePicker widget, walker menu, and Quick Settings tile mirroring
  the existing wallpaper picker, with color-swatch previews
- blob_wallpaper no longer forces dynamic mode on every wallpaper
  change; it only recolors if you're already in dynamic mode
- install.sh: fix a new-directory mkdir bug in backup_and_copy, and
  stop backing up wallpapers/themes (.bak dirs were showing up as
  fake entries in the picker) since both are pure git mirrors

Claude-Session: https://claude.ai/code/session_011kf23kB9NsaczSYazZsWs6
2026-07-31 22:14:51 -04:00
SirBlob cdff530e4b Fix gif wallpapers rendering static instead of animated
omarchy-theme-set launches swaybg asynchronously in the background,
which raced against the gif-detection logic and could leave a static
swaybg frame on top of the animated awww daemon. Skip theme-set's own
background step and own the daemon selection (swaybg vs awww) and
symlink update directly, launch awww-daemon through uwsm-app like
every other layer-shell client here, use awww's own graceful kill
instead of a raw pkill to avoid a stale IPC socket, and log daemon
output plus invocation env to ~/.cache for debugging.

Claude-Session: https://claude.ai/code/session_011kf23kB9NsaczSYazZsWs6
2026-07-31 16:01:34 -04:00
SirBlob bff3c13acc Add 20 wallpapers, rename to lowercase/no-spaces, rebuild gallery
Normalize wallpaper filenames (no capitals, no spaces) and regenerate
the alphabetical gallery split for the new 88-wallpaper total; m-r/r-z
replace n-r/s-z since the split boundaries shifted.

Claude-Session: https://claude.ai/code/session_011kf23kB9NsaczSYazZsWs6
2026-07-31 16:01:25 -04:00
SirBlob c2a05bbe8e Reapply "Add 25 new wallpapers, split gallery into wallpaper-gallery/"
This reverts commit 94518ffa30.
2026-07-31 13:48:24 -04:00
SirBlob 94518ffa30 Revert "Add 25 new wallpapers, split gallery into wallpaper-gallery/"
This reverts commit 07ef82ff73.
2026-07-31 13:46:46 -04:00
SirBlob 07ef82ff73 Add 25 new wallpapers, split gallery into wallpaper-gallery/
Move the wallpaper gallery docs into wallpaper-gallery/ (index +
alphabetical a-d/e-m/n-r/s-z pages) so the growing list stays readable,
and link the new structure from README.

Claude-Session: https://claude.ai/code/session_011kf23kB9NsaczSYazZsWs6
2026-07-31 13:44:31 -04:00
SirBlob 1ca522ddc0 Add mountain-snow-minima and vintage-ascent to wallpaper gallery 2026-07-27 12:32:53 -04:00
SirBlob f32b4ac102 Add mountain-snow-minima and vintage-ascent wallpapers 2026-07-27 12:31:07 -04:00
SirBlob 88f2740361 Extract commands.md from README, link wallpaper/keybinds/commands docs 2026-07-27 12:31:01 -04:00
SirBlob 5ecbcdf55b Stop side panels from stretching to center panel height 2026-07-27 12:26:51 -04:00
SirBlob c3f8738f00 Fix icon badge centering, remove uptime card, fix weather location, 3 tiles per row 2026-07-27 12:24:20 -04:00
SirBlob 9a2e352202 Center icon badges properly and split wallpaper tile row to 2 per row 2026-07-27 12:16:49 -04:00
SirBlob 0dd174d8c7 Move wallpaper button into tile grid, add breathing room to side card icons 2026-07-27 12:13:23 -04:00
SirBlob 0c0c914431 Fix missing icon glyphs on wallpaper, uptime, weather, and Claude Code cards 2026-07-27 12:09:55 -04:00
SirBlob cffe15e1f6 Widen side cards, add icon badges and graphics, add wallpaper button 2026-07-27 12:00:04 -04:00
SirBlob 9b839ffaf1 Read Claude Code usage from local session logs, redesign panel as separate cards 2026-07-27 11:54:11 -04:00
SirBlob c68e8c38cb Rename blob_claude_key to generic blob_key for storing multiple secrets 2026-07-27 11:41:14 -04:00
SirBlob fb57093a75 Add side panels with widget cards and Claude Code usage stats to quick settings 2026-07-27 11:39:54 -04:00
SirBlob 66a8482254 wallpaper update 2026-07-25 14:07:30 -04:00
SirBlob 692555f8e3 Add keybinds.md documenting custom Hyprland bindings 2026-07-16 10:37:28 -04:00
SirBlob 7cba2c0b3f Remove ChatGPT, Grok, X, Typora, and 1Password keybinds 2026-07-16 10:37:26 -04:00
SirBlob 83780c7ff1 Remove the Update.md 2026-07-03 16:24:40 -04:00
SirBlob ea7093e987 Update README for new widgets, blob_theme, and lid handling 2026-07-03 16:18:53 -04:00
91 changed files with 1479 additions and 148 deletions
+19 -11
View File
@@ -21,22 +21,21 @@ My current setup is built around these core components:
### Directory Structure
- **`hypr/`**: Hyprland configurations (keybindings, window rules, animations, layout settings, and autostart).
- **`hypr/`**: Hyprland configurations (keybindings, window rules, animations, monitor layout, lid-close display handling, and autostart). See [`hypr/keybinds.md`](hypr/keybinds.md) for custom keybindings.
- **`waybar/`**: Status bar layout, CSS styling, and custom interactive modules.
- **`ags/`**: Custom desktop widgets built with TypeScript and GTK.
- **`scripts/`**: Global utility scripts seamlessly exposed as commands by the installer.
- **`wallpapers/`**: A collection of local custom wallpapers for dynamic theming.
- **`ags/`**: Custom desktop widgets built with TypeScript and GTK — media player, notification hub, quick settings, system monitor, wallpaper picker, and theme picker.
- **`scripts/`**: Global utility scripts seamlessly exposed as commands by the installer. See [`commands.md`](commands.md).
- **`wallpapers/`**: A collection of local custom wallpapers for dynamic theming. See [`wallpaper-gallery/`](wallpaper-gallery/index.md) for the full gallery (split alphabetically across multiple pages).
- **`themes/`**: Drop-in local color themes (one `colors.toml` per theme) that `install.sh` deploys into Omarchy's theme directory. See [`themes/README.md`](themes/README.md).
- **`omarchy/hooks/`**: Event hooks for the Omarchy system (e.g. automatically applying dynamic themes when changing wallpapers).
- **`branding/`**: Custom ASCII art and system branding assets.
## Custom Commands
## Docs
The installer automatically exposes scripts from the `scripts/` directory as global commands:
- **`blob_wallpaper [path]`**: Sets your background using Omarchy's background system. If used with an image from `~/wallpapers/` or a valid path, it leverages Pywal to generate a full system color palette and dynamically updates the `blob-dynamic` theme, AGS widgets, and Waybar.
- **`blob_glass [on|off|toggle]`**: A quick toggle to enable or disable window transparency on the fly.
- **`blob_boot [path]`**: Safely updates your Plymouth boot splash image (defaults to `branding/boot_flash.png`) and rebuilds the `initramfs` (GRUB compatible via `mkinitcpio`).
- **`blob_wifi`**: A streamlined script to connect to the GMU Eduroam Wi-Fi network using `iwd` and `systemd-resolved` (replaces NetworkManager).
- [Wallpaper Gallery](wallpaper-gallery/index.md) — preview of every wallpaper in `wallpapers/`, split alphabetically across [0-9, A-E](wallpaper-gallery/a-d.md), [E-M](wallpaper-gallery/e-m.md), [M-R](wallpaper-gallery/m-r.md), [R-Y](wallpaper-gallery/r-z.md).
- [Themes](themes/README.md) — how to add a local color theme.
- [Keybinds](hypr/keybinds.md) — custom Hyprland keybindings on top of Omarchy's defaults.
- [Commands](commands.md) — custom `blob_*` CLI commands exposed by the installer.
## Installation
@@ -53,3 +52,12 @@ An automated installer script (`install.sh`) is provided to safely apply these c
./install.sh --force
```
The installer also configures the laptop lid switch so the machine stays awake (and the external monitors stay active) when docked or on AC power.
To roll back to the backups the installer created, use `revert.sh`:
```bash
# Restore configs from their .bak versions (prompts first)
./revert.sh
```
-56
View File
@@ -1,56 +0,0 @@
# Dotfiles
These are my omarchy dotfiles.
## Objective
I want you to make a couple additions and fixes to my config files.
## Developement and Coding Rules
You must follows these rule at all times
1. Do not add code comments
2. Do not run commands, I will test everything myself
3. Do not use emojies in documentation or the code
4. Keep code understandable and easy to read (name variables with easy to read names)
5. Do not give paragraph explanations unless asked.
## What I Want Done
1. I want you to add more widgets. I recently saw a dotfiles config with widgets for notification hub.
Look at ./ags-dots for ideas on how I was inspired. I want to keep my current omarchy theme and style.
2. I want a wallpaper selector like the in ./ags-dots. I want to be able to select a wallpaper from a widget, and it should change the wallpaper. This will replace the blob_wallpaper command.
3. I want to make a vercel website that I can upload a wallpaper, and it will generate a color theme for the wallpaper. It should work like my custom dynamic wallpaper generater. I want to be able to tweak and download the config files for the wallpaper. I want it to be responsive. Make it look modern and polished. Use Svelte 5 syntax and tailwindcss.
## My Laptop Specs
fastfetch
┌──────────────────────Hardware──────────────────────┐
█████████████████████████████████████████████████████  PC: 82Y0 (IdeaPad Flex 5 14IRU8)
█████████████████████████████████████████████████████ │ ├: 13th Gen Intel(R) Core(TM) i5-1335U (4+8) @ 4.60 GHz
████ ████ ████ │ ├: Intel Iris Xe Graphics @ 1.25 GHz [Integrated]
████ ████ ████ │ ├󱄄: 1920x1200 @ 1.5x in 14", 60 Hz [Built-in]
████ █████████████████████ ████████ ████ │ ├󰋊: 127.89 GiB / 213.19 GiB (60%) - ext4
████ █████████████████████ ████████ ████ │ ├: 3.62 GiB / 15.16 GiB (24%)
████ ████ ████ ████ └ └󰓡 : 0 B / 4.00 GiB (0%)
████ ████ ████ ████ └────────────────────────────────────────────────────┘
████ ████ ████ ████
████ ████ ████ ████ ┌──────────────────────Software──────────────────────┐
████ ████ ████ ████  OS: Omarchy 3.8.2
████ ████ ████ ████ │ ├󰘬: master
████████████ ████ ████ │ ├󰔫: stable
████████████ ████ ████ │ ├: Linux 7.0.9-arch2-1
████ ████ ████ ████ │ ├: Hyprland 0.55.2 (Wayland)
████ ████ ████ ████ │ ├: alacritty 0.17.0
████ ████ ████ ████ │ ├󰏖: 1250 (pacman)
████ ████ ████ ████ │ ├󰸌: Blob Dynamic ●●●●●●●●
████ ████ ████ ████ └ └: JetBrainsMono Nerd Font (9pt, Regular)
████ ████ ████ ████ └────────────────────────────────────────────────────┘
████ ██████████████████████████████████████ ████
████ ██████████████████████████████████████ ████ ┌────────────────Age / Uptime / Update───────────────┐
████ ████ ████ 󱦟 OS Age: 69 days
████ ████ ████ 󱫐 Uptime: 4 mins
████████████████████████████ ████████████████████  Update: Thursday, June 11 2026 at 13:13
████████████████████████████ ████████████████████ └────────────────────────────────────────────────────┘
+2
View File
@@ -4,6 +4,7 @@ import Media from "./widget/Media"
import NotificationCenter from "./widget/Notifications"
import QuickSettings from "./widget/QuickSettings"
import SysMonitor from "./widget/SysMonitor"
import ThemePicker from "./widget/ThemePicker"
import WallPicker from "./widget/WallPicker"
const SHOW_DESKTOP_MEDIA = false
@@ -25,6 +26,7 @@ app.start({
start("notification-center", NotificationCenter)
start("quick-settings", QuickSettings)
start("sys-monitor", SysMonitor)
start("theme-picker", ThemePicker)
start("wall-picker", WallPicker)
},
})
+32
View File
@@ -0,0 +1,32 @@
#!/bin/bash
PROJECTS_DIR="$HOME/.claude/projects"
TODAY=$(date -u '+%Y-%m-%d')
EMPTY='{"available":false,"tokens":0,"messages":0,"cacheHitPercent":0}'
if [ ! -d "$PROJECTS_DIR" ]; then
echo "$EMPTY"
exit 0
fi
FILES=$(find "$PROJECTS_DIR" -name "*.jsonl" -newermt "$TODAY")
if [ -z "$FILES" ]; then
echo '{"available":true,"tokens":0,"messages":0,"cacheHitPercent":0}'
exit 0
fi
jq -s --arg today "$TODAY" '
[.[] | select(.timestamp != null and (.timestamp | startswith($today)) and .message.usage != null) | .message.usage] as $usages
| ([$usages[] | .input_tokens // 0] | add // 0) as $input
| ([$usages[] | .output_tokens // 0] | add // 0) as $output
| ([$usages[] | .cache_creation_input_tokens // 0] | add // 0) as $cacheCreate
| ([$usages[] | .cache_read_input_tokens // 0] | add // 0) as $cacheRead
| ($input + $cacheCreate + $cacheRead) as $totalInput
| {
available: true,
tokens: ($totalInput + $output),
messages: ($usages | length),
cacheHitPercent: (if $totalInput > 0 then (($cacheRead / $totalInput) * 100) else 0 end)
}
' $FILES 2>/dev/null || echo "$EMPTY"
+17
View File
@@ -0,0 +1,17 @@
#!/bin/bash
LOCATION="Great+Falls,VA"
icon=$(omarchy-weather-icon 2>/dev/null)
weather=$(curl -fsS --max-time 4 "https://wttr.in/${LOCATION}?format=%l|%t|%w" 2>/dev/null | tr -d '\n')
if [[ -z $weather ]]; then
echo "Weather unavailable"
exit 1
fi
IFS='|' read -r place temperature wind <<< "$weather"
place=${place%%,*}
temperature=${temperature#+}
echo "$icon $place · Temp $temperature · Wind $wind"
+133 -10
View File
@@ -84,7 +84,8 @@
.QuickSettings,
.SysMonitor,
.Calendar,
.WallPicker {
.WallPicker,
.ThemePicker {
background-color: transparent;
}
@@ -349,6 +350,137 @@
font-size: 13px;
}
.theme-picker {
min-width: 680px;
min-height: 460px;
}
.theme-scroll {
min-height: 360px;
}
.theme-chip {
padding: 8px;
border-radius: 10px;
border: 2px solid transparent;
background-color: alpha(@color0, 0.6);
transition: all 0.2s;
min-width: 200px;
}
.theme-chip:hover {
border: 2px solid alpha(@accent, 0.6);
}
.theme-chip.active {
border: 2px solid @accent;
}
.theme-chip-dynamic {
background-color: alpha(@accent, 0.15);
}
.theme-chip-dynamic.active {
background-color: @accent;
}
.theme-chip-dynamic.active .theme-chip-label,
.theme-chip-dynamic.active .theme-chip-icon {
color: @background;
}
.theme-chip-icon {
font-size: 16px;
color: @accent;
}
.theme-swatches {
min-height: 36px;
border-radius: 6px;
}
.theme-swatch {
min-width: 10px;
}
.theme-chip-label {
font-size: 12px;
color: @foreground;
}
.qs-side-panel {
min-width: 240px;
}
.widget-card {
padding: 12px;
}
.widget-card-header {
margin-bottom: 2px;
}
.widget-icon-badge {
background-color: alpha(@accent, 0.18);
border-radius: 8px;
min-width: 32px;
min-height: 32px;
color: @accent;
font-size: 16px;
}
.widget-icon-badge label {
padding: 0;
}
.widget-card-title {
font-size: 13px;
font-weight: bold;
color: @foreground;
}
.widget-card-label {
font-size: 12px;
opacity: 0.8;
}
.widget-card-value {
font-size: 13px;
font-weight: bold;
color: @foreground;
}
.widget-card-empty {
font-size: 12px;
opacity: 0.6;
}
.widget-stat-row {
padding: 2px 0;
}
.widget-stat-icon {
color: @color5;
font-size: 13px;
min-width: 22px;
padding-right: 2px;
}
.widget-level-bar {
min-height: 6px;
}
.widget-level-bar trough {
min-height: 6px;
border-radius: 6px;
background-color: alpha(@foreground, 0.15);
}
.widget-level-bar block.filled {
border-radius: 6px;
background-color: @accent;
}
.control-center {
min-width: 360px;
}
@@ -357,15 +489,6 @@
margin-bottom: 2px;
}
.cc-uptime {
font-size: 13px;
color: @foreground;
}
.cc-uptime-icon {
color: @accent;
}
.cc-clock {
font-size: 22px;
font-weight: bold;
+56
View File
@@ -0,0 +1,56 @@
import { Gtk } from "ags/gtk3"
import { createPoll } from "ags/time"
import { shell } from "../lib/utils"
import { CardHeader, StatRow } from "./WidgetCard"
type ClaudeUsage = {
available: boolean
tokens: number
messages: number
cacheHitPercent: number
}
const usage = createPoll<ClaudeUsage>(
{ available: false, tokens: 0, messages: 0, cacheHitPercent: 0 },
60000,
shell("bash $HOME/.config/ags/lib/claude-usage.sh"),
(stdout) => {
try {
return JSON.parse(stdout.trim())
} catch {
return { available: false, tokens: 0, messages: 0, cacheHitPercent: 0 }
}
},
)
function formatTokens(tokens: number) {
if (tokens >= 1000000) return `${(tokens / 1000000).toFixed(2)}M`
if (tokens >= 1000) return `${(tokens / 1000).toFixed(1)}K`
return `${tokens}`
}
export function ClaudeUsageCard() {
return (
<box class="panel widget-card" vertical spacing={10}>
<CardHeader icon={""} title="Claude Code" />
<label
class="widget-card-empty"
label="No usage logs found"
xalign={0}
halign={Gtk.Align.START}
visible={usage.as((u) => !u.available)}
/>
<box vertical spacing={8} visible={usage.as((u) => u.available)}>
<StatRow icon={""} label="Tokens today" value={usage.as((u) => formatTokens(u.tokens))} />
<StatRow icon={""} label="Messages today" value={usage.as((u) => `${u.messages}`)} />
<box vertical spacing={4}>
<box spacing={8}>
<label class="widget-card-label" label="Cache hit rate" xalign={0} halign={Gtk.Align.START} hexpand />
<label class="widget-card-value" label={usage.as((u) => `${Math.round(u.cacheHitPercent)}%`)} />
</box>
<levelbar class="widget-level-bar" value={usage.as((u) => u.cacheHitPercent / 100)} />
</box>
</box>
</box>
)
}
+90 -9
View File
@@ -3,6 +3,8 @@ import { Astal, Gtk } from "ags/gtk3"
import { createState } from "ags"
import { createPoll, interval } from "ags/time"
import { sh, shell } from "../lib/utils"
import { ClaudeUsageCard } from "./ClaudeUsage"
import { CardHeader, StatRow } from "./WidgetCard"
export const QUICKSETTINGS_WINDOW = "quick-settings"
@@ -142,6 +144,16 @@ function Toggles() {
sh("omarchy-launch-bluetooth")
}}
/>
<Tile
icon={""}
label="Wallpaper"
onClicked={() => {
closePanel()
sh("blob_wallpaper")
}}
/>
</box>
<box class="qs-tiles" spacing={8} homogeneous>
<Tile
icon={""}
label="Silence"
@@ -151,8 +163,6 @@ function Toggles() {
sh("makoctl mode -t do-not-disturb")
}}
/>
</box>
<box class="qs-tiles" spacing={8} homogeneous>
<Tile
icon={""}
label="Night Light"
@@ -163,7 +173,17 @@ function Toggles() {
}}
/>
<Tile icon={""} label="Record" onClicked={() => { closePanel(); sh("omarchy-capture-screenrecording") }} />
</box>
<box class="qs-tiles" spacing={8} homogeneous>
<Tile icon={""} label="Pick Color" onClicked={() => { closePanel(); sh("hyprpicker -a") }} />
<Tile
icon={""}
label="Theme"
onClicked={() => {
closePanel()
sh("blob_theme")
}}
/>
</box>
</box>
)
@@ -306,6 +326,63 @@ function CalendarSection() {
)
}
type Weather = { ok: boolean; icon: string; place: string; temp: string; wind: string }
function parseWeather(raw: string): Weather {
const parts = raw.split(" · ")
if (parts.length < 3) return { ok: false, icon: "", place: raw, temp: "", wind: "" }
const match = parts[0].match(/^(\S+)\s*(.*)$/)
return {
ok: true,
icon: match ? match[1] : "",
place: match ? match[2].trim() : parts[0].trim(),
temp: parts[1].replace(/^Temp\s*/, ""),
wind: parts[2].replace(/^Wind\s*/, ""),
}
}
const weather = createPoll<Weather>(
{ ok: false, icon: "", place: "Loading...", temp: "", wind: "" },
600000,
shell("bash $HOME/.config/ags/lib/weather.sh"),
(stdout) => parseWeather(stdout.trim()),
)
function WeatherCard() {
return (
<box class="panel widget-card" vertical spacing={10}>
<CardHeader icon={weather.as((w) => w.icon)} title={weather.as((w) => w.place)} />
<label
class="widget-card-empty"
label="Weather unavailable"
xalign={0}
halign={Gtk.Align.START}
visible={weather.as((w) => !w.ok)}
/>
<box vertical spacing={8} visible={weather.as((w) => w.ok)}>
<StatRow icon={""} label="Temperature" value={weather.as((w) => w.temp)} />
<StatRow icon={""} label="Wind" value={weather.as((w) => w.wind)} />
</box>
</box>
)
}
function LeftPanel() {
return (
<box class="qs-side-panel" vertical spacing={12} valign={Gtk.Align.START}>
<WeatherCard />
</box>
)
}
function RightPanel() {
return (
<box class="qs-side-panel" vertical spacing={12} valign={Gtk.Align.START}>
<ClaudeUsageCard />
</box>
)
}
export default function QuickSettings() {
const { TOP } = Astal.WindowAnchor
@@ -321,13 +398,17 @@ export default function QuickSettings() {
visible={false}
application={app}
>
<box class="panel quick-settings control-center" vertical spacing={12}>
<Header />
<CalendarSection />
<Toggles />
<VolumeSlider />
<BrightnessSlider />
<MediaPlayer />
<box spacing={12}>
<LeftPanel />
<box class="panel quick-settings control-center" vertical spacing={12}>
<Header />
<CalendarSection />
<Toggles />
<VolumeSlider />
<BrightnessSlider />
<MediaPlayer />
</box>
<RightPanel />
</box>
</window>
)
+164
View File
@@ -0,0 +1,164 @@
import app from "ags/gtk3/app"
import { Astal, Gtk } from "ags/gtk3"
import { createPoll } from "ags/time"
import { For } from "ags"
import { sh, shell } from "../lib/utils"
export const THEMEPICKER_WINDOW = "theme-picker"
const COLUMNS = 3
type Theme = { slug: string; name: string; swatches: string[] }
const listCommand =
"{ find \"$HOME/.config/omarchy/themes\" -mindepth 1 -maxdepth 1 -type d 2>/dev/null; " +
"find \"$OMARCHY_PATH/themes\" -mindepth 1 -maxdepth 1 -type d 2>/dev/null; } | " +
"while read -r d; do " +
"[ -f \"$d/colors.toml\" ] || continue; " +
"n=$(basename \"$d\"); " +
"[ \"$n\" = blob-dynamic ] && continue; " +
"c=$(grep -E '^color[1-6] *=' \"$d/colors.toml\" | sed -E 's/^color[0-9]+ *= *\"?([^\"]*)\"?.*/\\1/' | paste -sd,); " +
"p=$(echo \"$n\" | sed -E 's/(^|-)([a-z])/\\1\\u\\2/g; s/-/ /g'); " +
"echo \"$n|$p|$c\"; " +
"done | awk -F'|' '!seen[$1]++' | sort -t'|' -k2,2"
const themes = createPoll<Theme[]>(
[],
5000,
shell(listCommand),
(stdout) =>
stdout
.split("\n")
.filter((line) => line.length > 0)
.map((line) => {
const [slug, name, swatchStr] = line.split("|")
return { slug, name: name ?? slug, swatches: (swatchStr ?? "").split(",").filter(Boolean) }
}),
)
const currentThemeName = createPoll(
"",
2000,
shell("cat \"$HOME/.config/omarchy/current/theme.name\" 2>/dev/null"),
(stdout) => stdout.trim(),
)
const isDynamic = currentThemeName.as((name) => name === "blob-dynamic")
const rows = themes.as((list) => {
const chunks: Theme[][] = []
for (let index = 0; index < list.length; index += COLUMNS) {
chunks.push(list.slice(index, index + COLUMNS))
}
return chunks
})
const applyTheme = (slug: string) => {
app.toggle_window(THEMEPICKER_WINDOW)
sh(`"$HOME/scripts/blob_theme.sh" "${slug}"`)
}
const applyDynamic = () => {
app.toggle_window(THEMEPICKER_WINDOW)
sh(`"$HOME/scripts/blob_theme.sh" --dynamic`)
}
function Swatches({ colors }: { colors: string[] }) {
return (
<box class="theme-swatches" spacing={0}>
{colors.map((color) => (
<box class="theme-swatch" css={`background-color: ${color};`} hexpand />
))}
</box>
)
}
function ThemeChip({ theme }: { theme: Theme }) {
const active = currentThemeName.as((name) => name === theme.slug)
return (
<button
class={active.as((on: boolean) => (on ? "theme-chip active" : "theme-chip"))}
onClicked={() => applyTheme(theme.slug)}
tooltipText={theme.name}
>
<box vertical spacing={6}>
<Swatches colors={theme.swatches} />
<label class="theme-chip-label" label={theme.name} maxWidthChars={16} />
</box>
</button>
)
}
function DynamicChip() {
return (
<button
class={isDynamic.as((on: boolean) =>
on ? "theme-chip theme-chip-dynamic active" : "theme-chip theme-chip-dynamic",
)}
onClicked={applyDynamic}
tooltipText="Recolor from the current wallpaper, without changing it"
>
<box spacing={8} halign={Gtk.Align.CENTER}>
<label class="theme-chip-icon" label={""} />
<label class="theme-chip-label" label="Dynamic (from wallpaper)" />
</box>
</button>
)
}
export default function ThemePicker() {
const hasThemes = themes.as((list) => list.length > 0)
const isEmpty = themes.as((list) => list.length === 0)
return (
<window
name={THEMEPICKER_WINDOW}
namespace={THEMEPICKER_WINDOW}
class="ThemePicker"
layer={Astal.Layer.OVERLAY}
keymode={Astal.Keymode.ON_DEMAND}
exclusivity={Astal.Exclusivity.NORMAL}
visible={false}
application={app}
>
<box class="panel theme-picker" vertical spacing={12}>
<box class="panel-header" spacing={8}>
<label class="panel-title" label="Themes" xalign={0} hexpand halign={Gtk.Align.START} />
<button
class="panel-icon-btn"
tooltipText="Close"
onClicked={() => app.toggle_window(THEMEPICKER_WINDOW)}
>
<label label={""} />
</button>
</box>
<DynamicChip />
<scrollable
class="theme-scroll"
visible={hasThemes}
hscroll={Gtk.PolicyType.NEVER}
vscroll={Gtk.PolicyType.AUTOMATIC}
>
<box vertical spacing={8}>
<For each={rows} id={(row: Theme[]) => row.map((t) => t.slug).join("|")}>
{(row: Theme[]) => (
<box spacing={8} halign={Gtk.Align.CENTER}>
{row.map((theme) => (
<ThemeChip theme={theme} />
))}
</box>
)}
</For>
</box>
</scrollable>
<box class="wall-empty" visible={isEmpty} vertical valign={Gtk.Align.CENTER}>
<label class="wall-empty-icon" label={""} halign={Gtk.Align.CENTER} />
<label class="wall-empty-text" label="No local themes found" halign={Gtk.Align.CENTER} />
</box>
</box>
</window>
)
}
+22
View File
@@ -0,0 +1,22 @@
import { Gtk } from "ags/gtk3"
export function CardHeader({ icon, title }: { icon: any; title: any }) {
return (
<box class="widget-card-header" spacing={10}>
<box class="widget-icon-badge">
<label label={icon} hexpand vexpand halign={Gtk.Align.CENTER} valign={Gtk.Align.CENTER} />
</box>
<label class="widget-card-title" label={title} xalign={0} halign={Gtk.Align.START} hexpand />
</box>
)
}
export function StatRow({ icon, label, value }: { icon: string; label: string; value: any }) {
return (
<box class="widget-stat-row" spacing={8}>
<label class="widget-stat-icon" label={icon} />
<label class="widget-card-label" label={label} xalign={0} halign={Gtk.Align.START} hexpand />
<label class="widget-card-value" label={value} />
</box>
)
}
+12
View File
@@ -0,0 +1,12 @@
# Custom Commands
The installer automatically exposes scripts from [`scripts/`](scripts/) as global commands.
| Command | Description |
| --- | --- |
| `blob_wallpaper [path]` | Sets your background using Omarchy's background system. If used with an image from `~/wallpapers/` or a valid path, it leverages Pywal to generate a full system color palette into the `blob-dynamic` theme and always updates the desktop background — but only switches your active color theme to it if you're already in dynamic mode (see `blob_theme --mode`), so it won't pull you out of a static theme. With no argument, it opens the AGS wallpaper picker. |
| `blob_theme [name\|--dynamic\|--mode\|--print\|share-link-or-id]` | Manages color themes. With no argument, opens the AGS theme picker. `--dynamic` recolors from the current wallpaper without changing it; `--mode` prints `static` or `dynamic`; `--print` dumps the currently active theme's `colors.toml` to stdout, e.g. `blob_theme --print > themes/my-theme/colors.toml` to save a dynamically-generated palette you like. A `name` applies a local theme (see [`themes/`](themes/README.md)) or, if no local theme matches, falls back to pulling a shared palette from the wall-styles site by link or id (e.g. `blob_theme "https://wall-styles.vercel.app/?id=ab12cd34ef"`). |
| `blob_glass [on\|off\|toggle]` | A quick toggle to enable or disable window transparency on the fly. |
| `blob_boot [path]` | Safely updates your Plymouth boot splash image (defaults to `branding/boot_flash.png`) and rebuilds the `initramfs` (GRUB compatible via `mkinitcpio`). |
| `blob_wifi` | A streamlined script to connect to the GMU Eduroam Wi-Fi network using `iwd` and `systemd-resolved` (replaces NetworkManager). |
| `blob_key <set\|show\|clear\|list> [NAME] [VALUE]` | Stores secrets/env values for widgets and services, e.g. `blob_key set SOME_TOKEN value`. |
+76
View File
@@ -0,0 +1,76 @@
Name = "blobThemeSelector"
NamePretty = "Blob's Theme Selector"
Cache = false
HideFromProviderlist = true
SearchName = true
local function ShellEscape(s)
return "'" .. s:gsub("'", "'\\''") .. "'"
end
function FormatName(slug)
local name = slug:gsub("-", " ")
name = name:gsub("%S+", function(word)
return word:sub(1, 1):upper() .. word:sub(2):lower()
end)
return name
end
function GetEntries()
local entries = {}
local home = os.getenv("HOME")
local omarchy_path = os.getenv("OMARCHY_PATH") or ""
entries[1] = {
Text = "Dynamic (from wallpaper)",
Value = "dynamic",
Actions = {
activate = "blob_theme --dynamic",
},
}
local dirs = {
home .. "/.config/omarchy/themes",
omarchy_path .. "/themes",
}
local seen = { ["blob-dynamic"] = true }
for _, themes_dir in ipairs(dirs) do
local handle = io.popen(
"find " .. ShellEscape(themes_dir) .. " -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sort"
)
if handle then
for theme_dir in handle:lines() do
local slug = theme_dir:match("([^/]+)$")
if slug and not seen[slug] then
local colors_file = io.open(theme_dir .. "/colors.toml", "r")
if colors_file then
colors_file:close()
seen[slug] = true
local entry = {
Text = FormatName(slug),
Value = slug,
Actions = {
activate = "blob_theme " .. ShellEscape(slug),
},
}
local preview_file = io.open(theme_dir .. "/preview.png", "r")
if preview_file then
preview_file:close()
entry.Preview = theme_dir .. "/preview.png"
entry.PreviewType = "file"
end
table.insert(entries, entry)
end
end
end
handle:close()
end
end
return entries
end
-6
View File
@@ -11,20 +11,14 @@ bindd = SUPER SHIFT, N, Editor, exec, omarchy-launch-editor
bindd = SUPER SHIFT, D, Docker, exec, omarchy-launch-tui lazydocker
bindd = SUPER SHIFT, G, Signal, exec, omarchy-launch-or-focus ^signal$ "uwsm-app -- signal-desktop"
bindd = SUPER SHIFT, O, Obsidian, exec, omarchy-launch-or-focus ^obsidian$ "uwsm-app -- obsidian -disable-gpu --enable-wayland-ime"
bindd = SUPER SHIFT, W, Typora, exec, uwsm-app -- typora --enable-wayland-ime
bindd = SUPER SHIFT, SLASH, Passwords, exec, uwsm-app -- 1password
# If your web app url contains #, type it as ## to prevent hyprland treating it as a comment
bindd = SUPER SHIFT, A, ChatGPT, exec, omarchy-launch-webapp "https://chatgpt.com"
bindd = SUPER SHIFT ALT, A, Grok, exec, omarchy-launch-webapp "https://grok.com"
bindd = SUPER SHIFT, C, Calendar, exec, omarchy-launch-webapp "https://app.hey.com/calendar/weeks/"
bindd = SUPER SHIFT, E, Email, exec, omarchy-launch-webapp "https://app.hey.com"
bindd = SUPER SHIFT, Y, YouTube, exec, omarchy-launch-webapp "https://youtube.com/"
bindd = SUPER SHIFT ALT, G, WhatsApp, exec, omarchy-launch-or-focus-webapp WhatsApp "https://web.whatsapp.com/"
bindd = SUPER SHIFT CTRL, G, Google Messages, exec, omarchy-launch-or-focus-webapp "Google Messages" "https://messages.google.com/web/conversations"
bindd = SUPER SHIFT, P, Google Photos, exec, omarchy-launch-or-focus-webapp "Google Photos" "https://photos.google.com/"
bindd = SUPER SHIFT, X, X, exec, omarchy-launch-webapp "https://x.com/"
bindd = SUPER SHIFT ALT, X, X Post, exec, omarchy-launch-webapp "https://x.com/compose/post"
# Add extra bindings
bindd = SUPER ALT, W, Wallpaper picker, exec, ags toggle wall-picker
+37
View File
@@ -0,0 +1,37 @@
# Custom Keybinds
Custom bindings on top of Omarchy's defaults, defined in `bindings.conf`.
## Apps
| Keybind | Action |
| --- | --- |
| `Super+Enter` | Terminal |
| `Super+Alt+Enter` | Terminal with tmux (attach or new "Work" session) |
| `Super+Shift+Enter` | Browser |
| `Super+Shift+F` | File manager |
| `Super+Alt+Shift+F` | File manager (opened at terminal's cwd) |
| `Super+Shift+B` | Browser |
| `Super+Shift+Alt+B` | Browser (private) |
| `Super+Shift+M` | Spotify |
| `Super+Shift+N` | Editor |
| `Super+Shift+D` | Docker (lazydocker) |
| `Super+Shift+G` | Signal |
| `Super+Shift+O` | Obsidian |
## Web Apps
| Keybind | Action |
| --- | --- |
| `Super+Shift+C` | Calendar (Hey) |
| `Super+Shift+E` | Email (Hey) |
| `Super+Shift+Y` | YouTube |
| `Super+Shift+Alt+G` | WhatsApp |
| `Super+Shift+Ctrl+G` | Google Messages |
| `Super+Shift+P` | Google Photos |
## Extras
| Keybind | Action |
| --- | --- |
| `Super+Alt+W` | Wallpaper picker |
+69 -2
View File
@@ -69,7 +69,7 @@ backup_and_copy() {
if [ ! -e "$dest" ]; then
echo "[COPY] $name: New directory (creating)"
mkdir -p "$(dirname "$dest")"
mkdir -p "$dest"
cp -r "$src"/* "$dest"/
return
fi
@@ -95,6 +95,40 @@ backup_and_copy() {
fi
}
# Like backup_and_copy, but for destinations that are pure git-tracked
# mirrors with no local state worth protecting (wallpapers, themes).
# No .bak sibling is created — a stale one would otherwise show up
# alongside the real thing (e.g. in the theme picker's directory scan).
replace_and_copy() {
local src="$1"
local dest="$2"
local name="$3"
if [ ! -e "$dest" ]; then
echo "[COPY] $name: New directory (creating)"
mkdir -p "$dest"
cp -r "$src"/* "$dest"/
return
fi
local src_hash=$(compute_hash "$src")
local dest_hash=$(compute_hash "$dest")
if [ "$src_hash" = "$dest_hash" ]; then
echo "[SKIP] $name: Up to date"
return
fi
if [ "$FORCE" = true ]; then
echo "[COPY] $name: Replacing (--force)"
rm -rf "$dest"
mkdir -p "$dest"
cp -r "$src"/* "$dest"/
else
echo "[SKIP] $name: Has local changes (use --force to overwrite)"
fi
}
install_dependencies() {
echo "=== Checking Dependencies ==="
local deps_needed=()
@@ -136,16 +170,23 @@ check_file "$SCRIPT_DIR/hypr/looknfeel.conf" "$HOME_DIR/.config/hypr/looknfeel.c
check_file "$SCRIPT_DIR/hypr/bindings.conf" "$HOME_DIR/.config/hypr/bindings.conf" "hypr/bindings.conf" || check_status=1
check_file "$SCRIPT_DIR/hypr/hypridle.conf" "$HOME_DIR/.config/hypr/hypridle.conf" "hypr/hypridle.conf" || check_status=1
check_file "$SCRIPT_DIR/omarchy/hooks/theme-set" "$HOME_DIR/.config/omarchy/hooks/theme-set" "omarchy/hooks/theme-set" || check_status=1
check_file "$SCRIPT_DIR/omarchy/themed/zen.css.tpl" "$HOME_DIR/.config/omarchy/themed/zen.css.tpl" "omarchy/themed/zen.css.tpl" || check_status=1
check_file "$SCRIPT_DIR/ags/app.ts" "$HOME_DIR/.config/ags/app.ts" "ags/app.ts" || check_status=1
check_file "$SCRIPT_DIR/ags/style.css" "$HOME_DIR/.config/ags/style.css" "ags/style.css" || check_status=1
check_file "$SCRIPT_DIR/ags/lib/utils.ts" "$HOME_DIR/.config/ags/lib/utils.ts" "ags/lib/utils.ts" || check_status=1
check_file "$SCRIPT_DIR/ags/lib/claude-usage.sh" "$HOME_DIR/.config/ags/lib/claude-usage.sh" "ags/lib/claude-usage.sh" || check_status=1
check_file "$SCRIPT_DIR/ags/lib/weather.sh" "$HOME_DIR/.config/ags/lib/weather.sh" "ags/lib/weather.sh" || check_status=1
check_file "$SCRIPT_DIR/ags/widget/ClaudeUsage.tsx" "$HOME_DIR/.config/ags/widget/ClaudeUsage.tsx" "ags/widget/ClaudeUsage.tsx" || check_status=1
check_file "$SCRIPT_DIR/ags/widget/Media.tsx" "$HOME_DIR/.config/ags/widget/Media.tsx" "ags/widget/Media.tsx" || check_status=1
check_file "$SCRIPT_DIR/ags/widget/Notifications.tsx" "$HOME_DIR/.config/ags/widget/Notifications.tsx" "ags/widget/Notifications.tsx" || check_status=1
check_file "$SCRIPT_DIR/ags/widget/QuickSettings.tsx" "$HOME_DIR/.config/ags/widget/QuickSettings.tsx" "ags/widget/QuickSettings.tsx" || check_status=1
check_file "$SCRIPT_DIR/ags/widget/SysMonitor.tsx" "$HOME_DIR/.config/ags/widget/SysMonitor.tsx" "ags/widget/SysMonitor.tsx" || check_status=1
check_file "$SCRIPT_DIR/ags/widget/ThemePicker.tsx" "$HOME_DIR/.config/ags/widget/ThemePicker.tsx" "ags/widget/ThemePicker.tsx" || check_status=1
check_file "$SCRIPT_DIR/ags/widget/WallPicker.tsx" "$HOME_DIR/.config/ags/widget/WallPicker.tsx" "ags/widget/WallPicker.tsx" || check_status=1
check_file "$SCRIPT_DIR/ags/widget/WidgetCard.tsx" "$HOME_DIR/.config/ags/widget/WidgetCard.tsx" "ags/widget/WidgetCard.tsx" || check_status=1
check_file "$SCRIPT_DIR/waybar/style.css" "$HOME_DIR/.config/waybar/style.css" "waybar/style.css" || check_status=1
check_file "$SCRIPT_DIR/elephant/menus/blob_background_selector.lua" "$HOME_DIR/.config/elephant/menus/blob_background_selector.lua" "elephant/menus/blob_background_selector.lua" || check_status=1
check_file "$SCRIPT_DIR/elephant/menus/blob_theme_selector.lua" "$HOME_DIR/.config/elephant/menus/blob_theme_selector.lua" "elephant/menus/blob_theme_selector.lua" || check_status=1
check_file "$SCRIPT_DIR/branding/about.txt" "$HOME_DIR/.config/omarchy/branding/about.txt" "branding/about.txt" || check_status=1
check_file "$SCRIPT_DIR/branding/screensaver.txt" "$HOME_DIR/.config/omarchy/branding/screensaver.txt" "branding/screensaver.txt" || check_status=1
@@ -161,6 +202,14 @@ for script in "$SCRIPT_DIR/scripts"/*.sh; do
fi
done
if [ -d "$SCRIPT_DIR/themes" ]; then
for theme_dir in "$SCRIPT_DIR/themes"/*/; do
[ -d "$theme_dir" ] || continue
theme_name=$(basename "$theme_dir")
check_file "$theme_dir/colors.toml" "$HOME_DIR/.config/omarchy/themes/$theme_name/colors.toml" "themes/$theme_name/colors.toml" || check_status=1
done
fi
echo ""
if [ "$CHECK" = true ]; then
@@ -187,7 +236,16 @@ backup_and_copy "$SCRIPT_DIR/hypr" "$HOME_DIR/.config/hypr" "Hyprland config"
backup_and_copy "$SCRIPT_DIR/branding" "$HOME_DIR/.config/omarchy/branding" "Branding files"
backup_and_copy "$SCRIPT_DIR/elephant" "$HOME_DIR/.config/elephant" "Elephant configs"
backup_and_copy "$SCRIPT_DIR/omarchy/hooks" "$HOME_DIR/.config/omarchy/hooks" "Omarchy hooks"
backup_and_copy "$SCRIPT_DIR/wallpapers" "$HOME_DIR/wallpapers" "Custom wallpapers"
backup_and_copy "$SCRIPT_DIR/omarchy/themed" "$HOME_DIR/.config/omarchy/themed" "Omarchy custom templates"
replace_and_copy "$SCRIPT_DIR/wallpapers" "$HOME_DIR/wallpapers" "Custom wallpapers"
if [ -d "$SCRIPT_DIR/themes" ]; then
for theme_dir in "$SCRIPT_DIR/themes"/*/; do
[ -d "$theme_dir" ] || continue
theme_name=$(basename "$theme_dir")
replace_and_copy "$theme_dir" "$HOME_DIR/.config/omarchy/themes/$theme_name" "Theme: $theme_name"
done
fi
zen_profile=$(find "$HOME_DIR/.config/zen" -maxdepth 1 -type d -name "*.Default (release)*" 2>/dev/null | head -n 1)
if [ -n "$zen_profile" ]; then
@@ -325,6 +383,15 @@ else
echo "Warning: hypridle not found. Please restart hypridle manually."
fi
echo ""
echo "=== Reapplying current theme (to pick up new templates) ==="
current_theme_name=$(cat "$HOME_DIR/.config/omarchy/current/theme.name" 2>/dev/null)
if [ -n "$current_theme_name" ] && command -v omarchy-theme-set &> /dev/null; then
OMARCHY_THEME_SKIP_BACKGROUND=1 omarchy-theme-set "$current_theme_name" || true
else
echo "Warning: no active theme found. Run blob_theme to generate zen.css."
fi
echo ""
echo "=== Installation Complete ==="
echo "Scripts are in: $HOME_DIR/scripts/"
+24
View File
@@ -0,0 +1,24 @@
/* Generated by omarchy-theme-set-templates from colors.toml on every
theme change (static, dynamic, or shared) - do not edit directly.
Consumed by zen/userChrome.css. */
:root {
--background: {{ background }};
--foreground: {{ foreground }};
--accent: {{ accent }};
--color0: {{ color0 }};
--color1: {{ color1 }};
--color2: {{ color2 }};
--color3: {{ color3 }};
--color4: {{ color4 }};
--color5: {{ color5 }};
--color6: {{ color6 }};
--color7: {{ color7 }};
--color8: {{ color8 }};
--color9: {{ color9 }};
--color10: {{ color10 }};
--color11: {{ color11 }};
--color12: {{ color12 }};
--color13: {{ color13 }};
--color14: {{ color14 }};
--color15: {{ color15 }};
}
+59
View File
@@ -0,0 +1,59 @@
#!/bin/bash
SECRETS_DIR="$HOME/.config/ags/secrets"
usage() {
echo "Usage: blob_key <set|show|clear|list> [NAME] [VALUE]"
echo " set <NAME> <VALUE> Store a secret (e.g. ANTHROPIC_ADMIN_KEY)"
echo " show <NAME> Print a stored secret, masked"
echo " clear <NAME> Remove a stored secret"
echo " list List the names of stored secrets"
exit 1
}
case "$1" in
set)
name="$2"
value="$3"
if [ -z "$name" ] || [ -z "$value" ]; then
echo "Usage: blob_key set <NAME> <VALUE>"
exit 1
fi
mkdir -p "$SECRETS_DIR"
printf '%s' "$value" > "$SECRETS_DIR/$name"
chmod 600 "$SECRETS_DIR/$name"
echo "Saved $name to $SECRETS_DIR/$name"
;;
show)
name="$2"
if [ -z "$name" ]; then
echo "Usage: blob_key show <NAME>"
exit 1
fi
if [ -f "$SECRETS_DIR/$name" ]; then
value=$(cat "$SECRETS_DIR/$name")
echo "${value:0:6}...${value: -4}"
else
echo "No key stored for $name"
fi
;;
clear)
name="$2"
if [ -z "$name" ]; then
echo "Usage: blob_key clear <NAME>"
exit 1
fi
rm -f "$SECRETS_DIR/$name"
echo "Removed $name"
;;
list)
if [ -d "$SECRETS_DIR" ]; then
ls -1 "$SECRETS_DIR"
else
echo "No keys stored"
fi
;;
*)
usage
;;
esac
+104 -34
View File
@@ -1,52 +1,119 @@
#!/bin/bash
# Pull a color theme shared from the wall-styles website and apply it.
# Manage color themes: local static themes installed under
# ~/.config/omarchy/themes/, the pywal-generated dynamic theme
# (blob-dynamic), and themes shared from the wall-styles website.
THEME_DIR="$HOME/.config/omarchy/themes/blob-dynamic"
USER_THEMES_DIR="$HOME/.config/omarchy/themes"
CURRENT_DIR="$HOME/.config/omarchy/current"
# Used only when a bare id is passed instead of a full share link.
# Override with: export BLOB_THEME_URL="https://your-deployment.vercel.app"
BASE_URL="${BLOB_THEME_URL:-https://wall-styles.vercel.app}"
if [ -z "$1" ]; then
echo "Usage: blob_theme <share-link-or-id>"
echo "Example: blob_theme \"https://wall-styles.vercel.app/?id=ab12cd34ef\""
exit 1
fi
slugify() {
echo "$1" | tr '[:upper:]' '[:lower:]' | tr ' ' '-'
}
INPUT="$1"
current_mode() {
local name
name=$(cat "$CURRENT_DIR/theme.name" 2>/dev/null)
if [ "$name" = "blob-dynamic" ]; then
echo "dynamic"
else
echo "static"
fi
}
if [[ "$INPUT" == http*://* ]]; then
HOST=$(echo "$INPUT" | sed -E 's#^(https?://[^/]+).*#\1#')
ID=$(echo "$INPUT" | grep -oE 'id=[A-Za-z0-9]+' | head -1 | cut -d= -f2)
if [ -z "$ID" ]; then
echo "Error: no theme id found in link '$INPUT'."
theme_exists_locally() {
local slug
slug=$(slugify "$1")
[ -d "$USER_THEMES_DIR/$slug" ] || [ -d "$OMARCHY_PATH/themes/$slug" ]
}
apply_static() {
local name="$1"
# Clean up a lingering gif-animation daemon from a previous dynamic
# wallpaper before switching to a static theme's own background.
awww kill --all >/dev/null 2>&1
omarchy-theme-set "$name"
}
apply_dynamic() {
if [ ! -f "$THEME_DIR/colors.toml" ]; then
echo "No dynamic theme yet. Pick a wallpaper first: blob_wallpaper"
exit 1
fi
API="$HOST/api/theme?id=$ID&format=toml"
else
API="$BASE_URL/api/theme?id=$INPUT&format=toml"
fi
# Skip the background step: this is purely a recolor of whatever
# wallpaper is already showing, not a wallpaper change.
OMARCHY_THEME_SKIP_BACKGROUND=1 omarchy-theme-set "blob-dynamic"
}
mkdir -p "$THEME_DIR/backgrounds"
case "$1" in
"")
ags toggle theme-picker
;;
--menu)
omarchy-launch-walker -m menus:blobThemeSelector --width 800 --minheight 400 -p "Select Theme…"
;;
--mode)
current_mode
;;
--print)
CURRENT_COLORS="$CURRENT_DIR/theme/colors.toml"
if [ ! -f "$CURRENT_COLORS" ]; then
echo "No active theme colors.toml found at $CURRENT_COLORS" >&2
exit 1
fi
# awk always terminates the last line with a newline, even if the
# source file doesn't. Omarchy's template engine reads colors.toml
# with a bash `while read` loop, which silently drops a final line
# missing its newline (e.g. color15) — some built-in themes are
# missing it too, so this guards every theme saved via --print.
awk '1' "$CURRENT_COLORS"
;;
--dynamic)
apply_dynamic
;;
*)
if theme_exists_locally "$1"; then
apply_static "$1"
else
# Not a local theme: treat it as a wall-styles share link or id.
INPUT="$1"
echo "Fetching theme..."
TMP=$(mktemp)
if ! curl -fsSL "$API" -o "$TMP"; then
echo "Error: could not fetch theme. The link may be expired (themes last one hour)."
rm -f "$TMP"
exit 1
fi
if [[ "$INPUT" == http*://* ]]; then
HOST=$(echo "$INPUT" | sed -E 's#^(https?://[^/]+).*#\1#')
ID=$(echo "$INPUT" | grep -oE 'id=[A-Za-z0-9]+' | head -1 | cut -d= -f2)
if [ -z "$ID" ]; then
echo "Error: '$INPUT' is not a local theme, and no share id was found in the link."
exit 1
fi
API="$HOST/api/theme?id=$ID&format=toml"
else
API="$BASE_URL/api/theme?id=$INPUT&format=toml"
fi
if ! grep -q '^background = ' "$TMP"; then
echo "Error: the response did not look like a valid colors.toml."
rm -f "$TMP"
exit 1
fi
mkdir -p "$THEME_DIR/backgrounds"
mv "$TMP" "$THEME_DIR/colors.toml"
echo "Fetching theme..."
TMP=$(mktemp)
if ! curl -fsSL "$API" -o "$TMP"; then
echo "Error: could not fetch theme, and '$1' is not a local theme name. The link may be expired (themes last one hour)."
rm -f "$TMP"
exit 1
fi
cat <<EOF > "$THEME_DIR/neovim.lua"
if ! grep -q '^background = ' "$TMP"; then
echo "Error: the response did not look like a valid colors.toml."
rm -f "$TMP"
exit 1
fi
mv "$TMP" "$THEME_DIR/colors.toml"
cat <<EOF > "$THEME_DIR/neovim.lua"
return {
{
"LazyVim/LazyVim",
@@ -57,7 +124,10 @@ return {
}
EOF
# Apply the Blob-Dynamic theme (reloads waybar, ags, etc.)
omarchy-theme-set "blob-dynamic"
# Apply the Blob-Dynamic theme (reloads waybar, ags, etc.)
omarchy-theme-set "blob-dynamic"
echo "Applied shared theme to blob-dynamic."
echo "Applied shared theme to blob-dynamic."
fi
;;
esac
+43 -16
View File
@@ -7,6 +7,14 @@ THEME_DIR="$HOME/.config/omarchy/themes/blob-dynamic"
mkdir -p "$WALLPAPER_DIR"
mkdir -p "$THEME_DIR/backgrounds"
{
echo "=== $(date '+%F %T') invoked with: $* ==="
echo "WAYLAND_DISPLAY=$WAYLAND_DISPLAY"
echo "XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR"
echo "DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS"
echo "PATH=$PATH"
} >> "$HOME/.cache/blob-wallpaper.log"
if [ -z "$1" ]; then
# Open the AGS wallpaper selector widget
ags toggle wall-picker
@@ -77,27 +85,46 @@ return {
}
EOF
# Apply the Blob-Dynamic theme
# omarchy-theme-set manages the background and reloads waybar and AGS
omarchy-theme-set "blob-dynamic"
# Only switch the active color theme to blob-dynamic if you're already
# in dynamic mode. The palette above and the background below are kept
# up to date regardless, so `blob_theme --dynamic` always reflects the
# latest wallpaper — but picking a wallpaper while on a static theme
# should change the wallpaper, not silently pull you out of it.
#
# When it does apply, skip omarchy-theme-set's own background step: it
# launches swaybg asynchronously, which races with the gif handling
# below and can leave a static swaybg frame on top of an animated gif.
CURRENT_THEME_NAME=$(cat "$HOME/.config/omarchy/current/theme.name" 2>/dev/null)
if [ "$CURRENT_THEME_NAME" = "blob-dynamic" ]; then
OMARCHY_THEME_SKIP_BACKGROUND=1 omarchy-theme-set "blob-dynamic"
fi
CURRENT_BACKGROUND_LINK="$HOME/.config/omarchy/current/background"
ln -nsf "$THEME_DIR/backgrounds/$(basename "$IMAGE_PATH")" "$CURRENT_BACKGROUND_LINK"
# Stop whichever daemon was previously rendering the background before
# starting the one this wallpaper needs. `awww kill` shuts the daemon down
# via its own IPC so it cleans up its socket, unlike a raw `pkill`.
pkill -x swaybg 2>/dev/null
awww kill --all >/dev/null 2>&1
pkill -x awww-daemon 2>/dev/null
# If it's a GIF, override swaybg with awww (swww replacement)
if [[ "${IMAGE_PATH,,}" == *.gif ]]; then
echo "GIF detected, switching to awww..."
pkill -x swaybg
echo "GIF detected, using awww for animation..."
setsid uwsm-app -- awww-daemon >>"$HOME/.cache/awww-daemon.log" 2>&1 &
# Start awww daemon if not running
if ! pgrep -x awww-daemon >/dev/null; then
awww-daemon >/dev/null 2>&1 &
sleep 1
# Poll until the daemon's IPC socket is ready instead of guessing a fixed sleep
IMG_ERROR=""
for _ in {1..15}; do
IMG_ERROR=$(awww img "$CURRENT_BACKGROUND_LINK" 2>&1) && break
sleep 0.3
done
if [[ -n "$IMG_ERROR" ]]; then
echo "awww failed to set the wallpaper: $IMG_ERROR"
echo "See $HOME/.cache/awww-daemon.log for daemon output."
fi
awww img "$IMAGE_PATH"
else
# Ensure awww is stopped for static wallpapers so swaybg can render them
if pgrep -x awww-daemon >/dev/null; then
pkill -x awww-daemon
fi
setsid uwsm-app -- swaybg -i "$CURRENT_BACKGROUND_LINK" -m fill >/dev/null 2>&1 &
fi
echo "Wallpaper and dynamic theme applied successfully: $IMAGE_PATH"
+60
View File
@@ -0,0 +1,60 @@
# Themes
Drop-in static color themes. Each subdirectory here becomes a theme
selectable from `blob_theme`, the theme picker widget, and the walker
menu, once `install.sh` copies it into `~/.config/omarchy/themes/`.
## Adding a theme
Create a directory named after the theme (lowercase, hyphens instead
of spaces — e.g. `tokyo-night/`) containing a `colors.toml`:
```toml
accent = "#7aa2f7"
cursor = "#c0caf5"
foreground = "#c0caf5"
background = "#1a1b26"
selection_foreground = "#1a1b26"
selection_background = "#7aa2f7"
color0 = "#1a1b26"
color1 = "#f7768e"
color2 = "#9ece6a"
color3 = "#e0af68"
color4 = "#7aa2f7"
color5 = "#bb9af7"
color6 = "#7dcfff"
color7 = "#c0caf5"
color8 = "#414868"
color9 = "#f7768e"
color10 = "#9ece6a"
color11 = "#e0af68"
color12 = "#7aa2f7"
color13 = "#bb9af7"
color14 = "#7dcfff"
color15 = "#c0caf5"
```
All 22 keys are required — this is the same format Omarchy themes and
`blob_wallpaper`'s pywal-generated `blob-dynamic` theme already use, so
`omarchy-theme-set` and its app-config templates pick it up with no
extra work.
### Saving a dynamic palette you like
If a wallpaper's pywal-generated colors are worth keeping permanently,
dump the currently active theme's `colors.toml` straight into a new
theme folder instead of typing it out by hand:
```bash
mkdir -p themes/my-new-theme
blob_theme --print > themes/my-new-theme/colors.toml
```
Run `./install.sh` (add `--force` if the theme already exists on disk
and you're updating it) to deploy new/changed theme folders.
Any theme already installed under `~/.config/omarchy/themes/` or
bundled with Omarchy itself (`$OMARCHY_PATH/themes/`) shows up
automatically too — this directory is just for ones you want tracked
in dotfiles.
+23
View File
@@ -0,0 +1,23 @@
accent = "#7babe3"
cursor = "#cbd2d9"
foreground = "#cbd2d9"
background = "#0f1012"
selection_foreground = "#0f1012"
selection_background = "#7babe3"
color0 = "#000000"
color1 = "#d53838"
color2 = "#38d4d5"
color3 = "#d58638"
color4 = "#d53886"
color5 = "#38d586"
color6 = "#3886d5"
color7 = "#d4d4d4"
color8 = "#949494"
color9 = "#d53838"
color10 = "#38d4d5"
color11 = "#d58638"
color12 = "#d53886"
color13 = "#38d586"
color14 = "#3886d5"
color15 = "#d4d4d4"
+23
View File
@@ -0,0 +1,23 @@
accent = "#d53838"
cursor = "#d4d4d4"
foreground = "#d4d4d4"
background = "#000000"
selection_foreground = "#000000"
selection_background = "#d53838"
color0 = "#000000"
color1 = "#d53838"
color2 = "#38d4d5"
color3 = "#d58638"
color4 = "#d53886"
color5 = "#38d586"
color6 = "#3886d5"
color7 = "#d4d4d4"
color8 = "#949494"
color9 = "#d53838"
color10 = "#38d4d5"
color11 = "#d58638"
color12 = "#d53886"
color13 = "#38d586"
color14 = "#3886d5"
color15 = "#d4d4d4"
+100
View File
@@ -0,0 +1,100 @@
# Wallpapers: 0-9, A-E
26 of 102 wallpapers in [`wallpapers/`](../wallpapers/). Sorted alphabetically.
[All wallpapers](index.md) | [E - M >>](e-m.md)
<table>
<tr>
<td align="center"><img src="../wallpapers/1_a-slient-voice.png" width="280"/></td>
<td align="center"><img src="../wallpapers/7_firewatch.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/anime_cafe_tokyonight.png" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>1_a-slient-voice.png</code></sub></td>
<td align="center"><sub><code>7_firewatch.jpg</code></sub></td>
<td align="center"><sub><code>anime_cafe_tokyonight.png</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/anime_circuit.png" width="280"/></td>
<td align="center"><img src="../wallpapers/anime_skyline.png" width="280"/></td>
<td align="center"><img src="../wallpapers/astronaut.jpg" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>anime_circuit.png</code></sub></td>
<td align="center"><sub><code>anime_skyline.png</code></sub></td>
<td align="center"><sub><code>astronaut.jpg</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/astronaut2.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/autumn_forest.png" width="280"/></td>
<td align="center"><img src="../wallpapers/awesome.png" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>astronaut2.jpg</code></sub></td>
<td align="center"><sub><code>autumn_forest.png</code></sub></td>
<td align="center"><sub><code>awesome.png</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/baby-star.png" width="280"/></td>
<td align="center"><img src="../wallpapers/be_productive_4k.png" width="280"/></td>
<td align="center"><img src="../wallpapers/black-hole.png" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>baby-star.png</code></sub></td>
<td align="center"><sub><code>be_productive_4k.png</code></sub></td>
<td align="center"><sub><code>black-hole.png</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/black_car_girl.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/camille-unknown.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/cat.jpg" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>black_car_girl.jpg</code></sub></td>
<td align="center"><sub><code>camille-unknown.jpg</code></sub></td>
<td align="center"><sub><code>cat.jpg</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/chainsaw_denji_cat.png" width="280"/></td>
<td align="center"><img src="../wallpapers/cherry_blossoms.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/clan_connections.png" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>chainsaw_denji_cat.png</code></sub></td>
<td align="center"><sub><code>cherry_blossoms.jpg</code></sub></td>
<td align="center"><sub><code>clan_connections.png</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/cliff-edge.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/colorful-planets.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/deer-forest.jpg" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>cliff-edge.jpg</code></sub></td>
<td align="center"><sub><code>colorful-planets.jpg</code></sub></td>
<td align="center"><sub><code>deer-forest.jpg</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/delorean.png" width="280"/></td>
<td align="center"><img src="../wallpapers/delorean_pastel.png" width="280"/></td>
<td align="center"><img src="../wallpapers/doom-slayer.png" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>delorean.png</code></sub></td>
<td align="center"><sub><code>delorean_pastel.png</code></sub></td>
<td align="center"><sub><code>doom-slayer.png</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/ds_giyu.png" width="280"/></td>
<td align="center"><img src="../wallpapers/evangelion.png" width="280"/></td>
<td></td>
</tr>
<tr>
<td align="center"><sub><code>ds_giyu.png</code></sub></td>
<td align="center"><sub><code>evangelion.png</code></sub></td>
<td></td>
</tr>
</table>
[All wallpapers](index.md) | [E - M >>](e-m.md)
+100
View File
@@ -0,0 +1,100 @@
# Wallpapers: E - M
26 of 102 wallpapers in [`wallpapers/`](../wallpapers/). Sorted alphabetically.
[<< 0-9, A-E](a-d.md) | [All wallpapers](index.md) | [M - R >>](m-r.md)
<table>
<tr>
<td align="center"><img src="../wallpapers/everblush_creep.png" width="280"/></td>
<td align="center"><img src="../wallpapers/firewatch_purple.png" width="280"/></td>
<td align="center"><img src="../wallpapers/fishSchool.jpeg" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>everblush_creep.png</code></sub></td>
<td align="center"><sub><code>firewatch_purple.png</code></sub></td>
<td align="center"><sub><code>fishSchool.jpeg</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/goblin_slayer.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/goldfish.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/hello-worlds.png" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>goblin_slayer.jpg</code></sub></td>
<td align="center"><sub><code>goldfish.jpg</code></sub></td>
<td align="center"><sub><code>hello-worlds.png</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/hollow-knight-2.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/hollow-knight-3.png" width="280"/></td>
<td align="center"><img src="../wallpapers/hollow-knight.jpg" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>hollow-knight-2.jpg</code></sub></td>
<td align="center"><sub><code>hollow-knight-3.png</code></sub></td>
<td align="center"><sub><code>hollow-knight.jpg</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/home127-dark.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/jellyfish.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/jupiter.png" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>home127-dark.jpg</code></sub></td>
<td align="center"><sub><code>jellyfish.jpg</code></sub></td>
<td align="center"><sub><code>jupiter.png</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/kimi_no_nawa.png" width="280"/></td>
<td align="center"><img src="../wallpapers/kingler_drawing.png" width="280"/></td>
<td align="center"><img src="../wallpapers/krita_digiart.png" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>kimi_no_nawa.png</code></sub></td>
<td align="center"><sub><code>kingler_drawing.png</code></sub></td>
<td align="center"><sub><code>krita_digiart.png</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/large_asf_goodbg.png" width="280"/></td>
<td align="center"><img src="../wallpapers/literal-wallpaper.png" width="280"/></td>
<td align="center"><img src="../wallpapers/makima-oxo.png" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>large_asf_goodbg.png</code></sub></td>
<td align="center"><sub><code>literal-wallpaper.png</code></sub></td>
<td align="center"><sub><code>makima-oxo.png</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/material_pastel_1.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/material_pastel_2.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/material_pastel_3.jpg" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>material_pastel_1.jpg</code></sub></td>
<td align="center"><sub><code>material_pastel_2.jpg</code></sub></td>
<td align="center"><sub><code>material_pastel_3.jpg</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/material_pastel_4.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/material_pastel_5.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/material_pastel_6.jpg" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>material_pastel_4.jpg</code></sub></td>
<td align="center"><sub><code>material_pastel_5.jpg</code></sub></td>
<td align="center"><sub><code>material_pastel_6.jpg</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/material_pastel_7.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/material_pastel_8.jpg" width="280"/></td>
<td></td>
</tr>
<tr>
<td align="center"><sub><code>material_pastel_7.jpg</code></sub></td>
<td align="center"><sub><code>material_pastel_8.jpg</code></sub></td>
<td></td>
</tr>
</table>
[<< 0-9, A-E](a-d.md) | [All wallpapers](index.md) | [M - R >>](m-r.md)
+8
View File
@@ -0,0 +1,8 @@
# Wallpapers
A gallery of all 102 wallpapers in [`wallpapers/`](../wallpapers/), sorted alphabetically and split across pages:
- [0-9, A-E](a-d.md) &mdash; 26 wallpapers (`1_a-slient-voice.png` to `evangelion.png`)
- [E - M](e-m.md) &mdash; 26 wallpapers (`everblush_creep.png` to `material_pastel_8.jpg`)
- [M - R](m-r.md) &mdash; 25 wallpapers (`melting_astro.jpg` to `rm-rf.jpg`)
- [R - Y](r-z.md) &mdash; 25 wallpapers (`rocket_launch.png` to `yosemite-lowpoly.jpg`)
+100
View File
@@ -0,0 +1,100 @@
# Wallpapers: M - R
25 of 102 wallpapers in [`wallpapers/`](../wallpapers/). Sorted alphabetically.
[<< E - M](e-m.md) | [All wallpapers](index.md) | [R - Y >>](r-z.md)
<table>
<tr>
<td align="center"><img src="../wallpapers/melting_astro.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/montains.png" width="280"/></td>
<td align="center"><img src="../wallpapers/mountain-snow-minima.jpg" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>melting_astro.jpg</code></sub></td>
<td align="center"><sub><code>montains.png</code></sub></td>
<td align="center"><sub><code>mountain-snow-minima.jpg</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/nasa1.png" width="280"/></td>
<td align="center"><img src="../wallpapers/neon-singularity.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/nighttab_backdrop.jpg" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>nasa1.png</code></sub></td>
<td align="center"><sub><code>neon-singularity.jpg</code></sub></td>
<td align="center"><sub><code>nighttab_backdrop.jpg</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/nord-chainsaw.png" width="280"/></td>
<td align="center"><img src="../wallpapers/nord_car_live.gif" width="280"/></td>
<td align="center"><img src="../wallpapers/nord_minimal_cat.png" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>nord-chainsaw.png</code></sub></td>
<td align="center"><sub><code>nord_car_live.gif</code></sub></td>
<td align="center"><sub><code>nord_minimal_cat.png</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/nord_sky.jpeg" width="280"/></td>
<td align="center"><img src="../wallpapers/nordic-heroin.png" width="280"/></td>
<td align="center"><img src="../wallpapers/p3.png" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>nord_sky.jpeg</code></sub></td>
<td align="center"><sub><code>nordic-heroin.png</code></sub></td>
<td align="center"><sub><code>p3.png</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/pacman-black.png" width="280"/></td>
<td align="center"><img src="../wallpapers/pastel-car-girl.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/pastel-car.png" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>pacman-black.png</code></sub></td>
<td align="center"><sub><code>pastel-car-girl.jpg</code></sub></td>
<td align="center"><sub><code>pastel-car.png</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/pastel-city.png" width="280"/></td>
<td align="center"><img src="../wallpapers/peaks.png" width="280"/></td>
<td align="center"><img src="../wallpapers/perfect-blue.jpg" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>pastel-city.png</code></sub></td>
<td align="center"><sub><code>peaks.png</code></sub></td>
<td align="center"><sub><code>perfect-blue.jpg</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/pixel-city.png" width="280"/></td>
<td align="center"><img src="../wallpapers/pixel-earth.png" width="280"/></td>
<td align="center"><img src="../wallpapers/planet_minimal.png" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>pixel-city.png</code></sub></td>
<td align="center"><sub><code>pixel-earth.png</code></sub></td>
<td align="center"><sub><code>planet_minimal.png</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/pokemon-legends-arceus-wallpapers.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/rain_world1.png" width="280"/></td>
<td align="center"><img src="../wallpapers/rain_world2.png" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>pokemon-legends-arceus-wallpapers.jpg</code></sub></td>
<td align="center"><sub><code>rain_world1.png</code></sub></td>
<td align="center"><sub><code>rain_world2.png</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/rm-rf.jpg" width="280"/></td>
<td></td>
<td></td>
</tr>
<tr>
<td align="center"><sub><code>rm-rf.jpg</code></sub></td>
<td></td>
<td></td>
</tr>
</table>
[<< E - M](e-m.md) | [All wallpapers](index.md) | [R - Y >>](r-z.md)
+100
View File
@@ -0,0 +1,100 @@
# Wallpapers: R - Y
25 of 102 wallpapers in [`wallpapers/`](../wallpapers/). Sorted alphabetically.
[<< M - R](m-r.md) | [All wallpapers](index.md)
<table>
<tr>
<td align="center"><img src="../wallpapers/rocket_launch.png" width="280"/></td>
<td align="center"><img src="../wallpapers/sakura.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/shiny-colors.png" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>rocket_launch.png</code></sub></td>
<td align="center"><sub><code>sakura.jpg</code></sub></td>
<td align="center"><sub><code>shiny-colors.png</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/shooting_stars.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/siri.png" width="280"/></td>
<td align="center"><img src="../wallpapers/space-juice.png" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>shooting_stars.jpg</code></sub></td>
<td align="center"><sub><code>siri.png</code></sub></td>
<td align="center"><sub><code>space-juice.png</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/space_man.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/space_piano.png" width="280"/></td>
<td align="center"><img src="../wallpapers/sushi_dark.png" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>space_man.jpg</code></sub></td>
<td align="center"><sub><code>space_piano.png</code></sub></td>
<td align="center"><sub><code>sushi_dark.png</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/swords.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/tabs.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/think.png" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>swords.jpg</code></sub></td>
<td align="center"><sub><code>tabs.jpg</code></sub></td>
<td align="center"><sub><code>think.png</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/train_tokyo.gif" width="280"/></td>
<td align="center"><img src="../wallpapers/trigonometry.png" width="280"/></td>
<td align="center"><img src="../wallpapers/two-astronauts.png" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>train_tokyo.gif</code></sub></td>
<td align="center"><sub><code>trigonometry.png</code></sub></td>
<td align="center"><sub><code>two-astronauts.png</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/underwater.png" width="280"/></td>
<td align="center"><img src="../wallpapers/vintage-ascent.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/windows-black.png" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>underwater.png</code></sub></td>
<td align="center"><sub><code>vintage-ascent.jpg</code></sub></td>
<td align="center"><sub><code>windows-black.png</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/windows-error.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/windows-magenta-blue.png" width="280"/></td>
<td align="center"><img src="../wallpapers/windows-magenta-pink.png" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>windows-error.jpg</code></sub></td>
<td align="center"><sub><code>windows-magenta-blue.png</code></sub></td>
<td align="center"><sub><code>windows-magenta-pink.png</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/windows-xp.png" width="280"/></td>
<td align="center"><img src="../wallpapers/xavier-cuenca-w4-3.jpg" width="280"/></td>
<td align="center"><img src="../wallpapers/yosemite-color-block.png" width="280"/></td>
</tr>
<tr>
<td align="center"><sub><code>windows-xp.png</code></sub></td>
<td align="center"><sub><code>xavier-cuenca-w4-3.jpg</code></sub></td>
<td align="center"><sub><code>yosemite-color-block.png</code></sub></td>
</tr>
<tr>
<td align="center"><img src="../wallpapers/yosemite-lowpoly.jpg" width="280"/></td>
<td></td>
<td></td>
</tr>
<tr>
<td align="center"><sub><code>yosemite-lowpoly.jpg</code></sub></td>
<td></td>
<td></td>
</tr>
</table>
[<< M - R](m-r.md) | [All wallpapers](index.md)
Binary file not shown.

After

Width:  |  Height:  |  Size: 921 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 901 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1021 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1018 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 495 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 974 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 820 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 687 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 726 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 599 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 817 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 755 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 KiB

+4 -2
View File
@@ -1,5 +1,7 @@
/* Import Omarchy Pywal-generated system colors */
@import url("file:///home/blob/.cache/wal/colors.css");
/* Import the active Omarchy theme's colors (regenerated from colors.toml
on every theme change - static, dynamic, or shared - by
omarchy-theme-set-templates via omarchy/themed/zen.css.tpl) */
@import url("file:///home/blob/.config/omarchy/current/theme/zen.css");
:root {
/* Map Omarchy colors to Zen variables */