Compare commits

...
25 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
90 changed files with 1470 additions and 93 deletions
+10 -12
View File
@@ -21,23 +21,21 @@ My current setup is built around these core components:
### Directory Structure ### Directory Structure
- **`hypr/`**: Hyprland configurations (keybindings, window rules, animations, monitor layout, lid-close display handling, 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. - **`waybar/`**: Status bar layout, CSS styling, and custom interactive modules.
- **`ags/`**: Custom desktop widgets built with TypeScript and GTK — media player, notification hub, quick settings, system monitor, and wallpaper picker. - **`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. - **`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. - **`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). - **`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. - **`branding/`**: Custom ASCII art and system branding assets.
## Custom Commands ## Docs
The installer automatically exposes scripts from the `scripts/` directory as global commands: - [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.
- **`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. - [Keybinds](hypr/keybinds.md) — custom Hyprland keybindings on top of Omarchy's defaults.
- **`blob_theme <share-link-or-id>`**: Pulls a color palette shared from the wall-styles site and applies it as the `blob-dynamic` theme (e.g. `blob_theme "https://wall-styles.vercel.app/?id=ab12cd34ef"`). - [Commands](commands.md) — custom `blob_*` CLI commands exposed by the installer.
- **`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).
## Installation ## Installation
+2
View File
@@ -4,6 +4,7 @@ import Media from "./widget/Media"
import NotificationCenter from "./widget/Notifications" import NotificationCenter from "./widget/Notifications"
import QuickSettings from "./widget/QuickSettings" import QuickSettings from "./widget/QuickSettings"
import SysMonitor from "./widget/SysMonitor" import SysMonitor from "./widget/SysMonitor"
import ThemePicker from "./widget/ThemePicker"
import WallPicker from "./widget/WallPicker" import WallPicker from "./widget/WallPicker"
const SHOW_DESKTOP_MEDIA = false const SHOW_DESKTOP_MEDIA = false
@@ -25,6 +26,7 @@ app.start({
start("notification-center", NotificationCenter) start("notification-center", NotificationCenter)
start("quick-settings", QuickSettings) start("quick-settings", QuickSettings)
start("sys-monitor", SysMonitor) start("sys-monitor", SysMonitor)
start("theme-picker", ThemePicker)
start("wall-picker", WallPicker) 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, .QuickSettings,
.SysMonitor, .SysMonitor,
.Calendar, .Calendar,
.WallPicker { .WallPicker,
.ThemePicker {
background-color: transparent; background-color: transparent;
} }
@@ -349,6 +350,137 @@
font-size: 13px; 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 { .control-center {
min-width: 360px; min-width: 360px;
} }
@@ -357,15 +489,6 @@
margin-bottom: 2px; margin-bottom: 2px;
} }
.cc-uptime {
font-size: 13px;
color: @foreground;
}
.cc-uptime-icon {
color: @accent;
}
.cc-clock { .cc-clock {
font-size: 22px; font-size: 22px;
font-weight: bold; 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 { createState } from "ags"
import { createPoll, interval } from "ags/time" import { createPoll, interval } from "ags/time"
import { sh, shell } from "../lib/utils" import { sh, shell } from "../lib/utils"
import { ClaudeUsageCard } from "./ClaudeUsage"
import { CardHeader, StatRow } from "./WidgetCard"
export const QUICKSETTINGS_WINDOW = "quick-settings" export const QUICKSETTINGS_WINDOW = "quick-settings"
@@ -142,6 +144,16 @@ function Toggles() {
sh("omarchy-launch-bluetooth") sh("omarchy-launch-bluetooth")
}} }}
/> />
<Tile
icon={""}
label="Wallpaper"
onClicked={() => {
closePanel()
sh("blob_wallpaper")
}}
/>
</box>
<box class="qs-tiles" spacing={8} homogeneous>
<Tile <Tile
icon={""} icon={""}
label="Silence" label="Silence"
@@ -151,8 +163,6 @@ function Toggles() {
sh("makoctl mode -t do-not-disturb") sh("makoctl mode -t do-not-disturb")
}} }}
/> />
</box>
<box class="qs-tiles" spacing={8} homogeneous>
<Tile <Tile
icon={""} icon={""}
label="Night Light" label="Night Light"
@@ -163,7 +173,17 @@ function Toggles() {
}} }}
/> />
<Tile icon={""} label="Record" onClicked={() => { closePanel(); sh("omarchy-capture-screenrecording") }} /> <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="Pick Color" onClicked={() => { closePanel(); sh("hyprpicker -a") }} />
<Tile
icon={""}
label="Theme"
onClicked={() => {
closePanel()
sh("blob_theme")
}}
/>
</box> </box>
</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() { export default function QuickSettings() {
const { TOP } = Astal.WindowAnchor const { TOP } = Astal.WindowAnchor
@@ -321,13 +398,17 @@ export default function QuickSettings() {
visible={false} visible={false}
application={app} application={app}
> >
<box class="panel quick-settings control-center" vertical spacing={12}> <box spacing={12}>
<Header /> <LeftPanel />
<CalendarSection /> <box class="panel quick-settings control-center" vertical spacing={12}>
<Toggles /> <Header />
<VolumeSlider /> <CalendarSection />
<BrightnessSlider /> <Toggles />
<MediaPlayer /> <VolumeSlider />
<BrightnessSlider />
<MediaPlayer />
</box>
<RightPanel />
</box> </box>
</window> </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, 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, 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, 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 # 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, 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, 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, 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 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 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, 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 # Add extra bindings
bindd = SUPER ALT, W, Wallpaper picker, exec, ags toggle wall-picker 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 if [ ! -e "$dest" ]; then
echo "[COPY] $name: New directory (creating)" echo "[COPY] $name: New directory (creating)"
mkdir -p "$(dirname "$dest")" mkdir -p "$dest"
cp -r "$src"/* "$dest"/ cp -r "$src"/* "$dest"/
return return
fi fi
@@ -95,6 +95,40 @@ backup_and_copy() {
fi 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() { install_dependencies() {
echo "=== Checking Dependencies ===" echo "=== Checking Dependencies ==="
local deps_needed=() 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/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/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/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/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/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/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/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/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/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/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/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/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_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/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 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 fi
done 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 "" echo ""
if [ "$CHECK" = true ]; then 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/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/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/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) 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 if [ -n "$zen_profile" ]; then
@@ -325,6 +383,15 @@ else
echo "Warning: hypridle not found. Please restart hypridle manually." echo "Warning: hypridle not found. Please restart hypridle manually."
fi 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 ""
echo "=== Installation Complete ===" echo "=== Installation Complete ==="
echo "Scripts are in: $HOME_DIR/scripts/" 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 #!/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" 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. # 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" # Override with: export BLOB_THEME_URL="https://your-deployment.vercel.app"
BASE_URL="${BLOB_THEME_URL:-https://wall-styles.vercel.app}" BASE_URL="${BLOB_THEME_URL:-https://wall-styles.vercel.app}"
if [ -z "$1" ]; then slugify() {
echo "Usage: blob_theme <share-link-or-id>" echo "$1" | tr '[:upper:]' '[:lower:]' | tr ' ' '-'
echo "Example: blob_theme \"https://wall-styles.vercel.app/?id=ab12cd34ef\"" }
exit 1
fi
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 theme_exists_locally() {
HOST=$(echo "$INPUT" | sed -E 's#^(https?://[^/]+).*#\1#') local slug
ID=$(echo "$INPUT" | grep -oE 'id=[A-Za-z0-9]+' | head -1 | cut -d= -f2) slug=$(slugify "$1")
if [ -z "$ID" ]; then [ -d "$USER_THEMES_DIR/$slug" ] || [ -d "$OMARCHY_PATH/themes/$slug" ]
echo "Error: no theme id found in link '$INPUT'." }
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 exit 1
fi fi
API="$HOST/api/theme?id=$ID&format=toml" # Skip the background step: this is purely a recolor of whatever
else # wallpaper is already showing, not a wallpaper change.
API="$BASE_URL/api/theme?id=$INPUT&format=toml" OMARCHY_THEME_SKIP_BACKGROUND=1 omarchy-theme-set "blob-dynamic"
fi }
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..." if [[ "$INPUT" == http*://* ]]; then
TMP=$(mktemp) HOST=$(echo "$INPUT" | sed -E 's#^(https?://[^/]+).*#\1#')
if ! curl -fsSL "$API" -o "$TMP"; then ID=$(echo "$INPUT" | grep -oE 'id=[A-Za-z0-9]+' | head -1 | cut -d= -f2)
echo "Error: could not fetch theme. The link may be expired (themes last one hour)." if [ -z "$ID" ]; then
rm -f "$TMP" echo "Error: '$INPUT' is not a local theme, and no share id was found in the link."
exit 1 exit 1
fi 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 mkdir -p "$THEME_DIR/backgrounds"
echo "Error: the response did not look like a valid colors.toml."
rm -f "$TMP"
exit 1
fi
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 { return {
{ {
"LazyVim/LazyVim", "LazyVim/LazyVim",
@@ -57,7 +124,10 @@ return {
} }
EOF EOF
# Apply the Blob-Dynamic theme (reloads waybar, ags, etc.) # Apply the Blob-Dynamic theme (reloads waybar, ags, etc.)
omarchy-theme-set "blob-dynamic" 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 "$WALLPAPER_DIR"
mkdir -p "$THEME_DIR/backgrounds" 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 if [ -z "$1" ]; then
# Open the AGS wallpaper selector widget # Open the AGS wallpaper selector widget
ags toggle wall-picker ags toggle wall-picker
@@ -77,27 +85,46 @@ return {
} }
EOF EOF
# Apply the Blob-Dynamic theme # Only switch the active color theme to blob-dynamic if you're already
# omarchy-theme-set manages the background and reloads waybar and AGS # in dynamic mode. The palette above and the background below are kept
omarchy-theme-set "blob-dynamic" # 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 if [[ "${IMAGE_PATH,,}" == *.gif ]]; then
echo "GIF detected, switching to awww..." echo "GIF detected, using awww for animation..."
pkill -x swaybg setsid uwsm-app -- awww-daemon >>"$HOME/.cache/awww-daemon.log" 2>&1 &
# Start awww daemon if not running # Poll until the daemon's IPC socket is ready instead of guessing a fixed sleep
if ! pgrep -x awww-daemon >/dev/null; then IMG_ERROR=""
awww-daemon >/dev/null 2>&1 & for _ in {1..15}; do
sleep 1 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 fi
awww img "$IMAGE_PATH"
else else
# Ensure awww is stopped for static wallpapers so swaybg can render them setsid uwsm-app -- swaybg -i "$CURRENT_BACKGROUND_LINK" -m fill >/dev/null 2>&1 &
if pgrep -x awww-daemon >/dev/null; then
pkill -x awww-daemon
fi
fi fi
echo "Wallpaper and dynamic theme applied successfully: $IMAGE_PATH" 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 the active Omarchy theme's colors (regenerated from colors.toml
@import url("file:///home/blob/.cache/wal/colors.css"); 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 { :root {
/* Map Omarchy colors to Zen variables */ /* Map Omarchy colors to Zen variables */