Compare commits
13 Commits
804ec54090
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 2d5a4e9f4c | |||
| 8d2aa49668 | |||
| f60b7e263b | |||
| b148fcc256 | |||
| 09c8706f35 | |||
| 9d788d42e1 | |||
| 086097f2a9 | |||
| 1755d17558 | |||
| 9e310d2f58 | |||
| 21dbb16e8b | |||
| 5cfa02ea6b | |||
| f57dc1db3c | |||
| 260b202d6f |
@@ -1 +1,2 @@
|
||||
sunsetr/.config/sunsetr/geo.toml
|
||||
resources/ai/sessions
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
# AGENTS.md
|
||||
|
||||
Guidance for AI agents (and humans) working on this repo. This file documents
|
||||
how AI assistance has been used on this project and the expectations for future
|
||||
sessions.
|
||||
|
||||
## What this repo is
|
||||
|
||||
A set of GNU-stow packages containing the user's machine configuration
|
||||
(Hyprland desktop, terminal, shell, systemd units, scripts, wallpapers). Each
|
||||
top-level directory is a stow package rooted at `$HOME` (or `/` for system
|
||||
dirs like `etc`). See `README.md` for the full package table and quick start.
|
||||
|
||||
## How AI has been used here
|
||||
|
||||
All prior work is captured in session transcripts under
|
||||
`resources/ai/sessions/`. The main efforts so far:
|
||||
|
||||
- **Hyprland migration to Lua** (`session-ses_ffd7.md`): converted the
|
||||
hyprlang `.conf` configs to Lua configs for Hyprland 0.56.2, migrated
|
||||
plugins and themes (Catppuccin Mocha palette lives in `hyprmocha/`).
|
||||
- **uwsm/sddm sign-in debugging** (`session-ses_ffd3.md`): diagnosed why the
|
||||
uwsm Hyprland session would not allow sign-in; added a `sudo-askpass.sh`
|
||||
(zenity prompt via `SUDO_ASKPASS`) and disabled linger.
|
||||
- **Performance work** (`session-ses_ffcb.md`): profiled Hyprland CPU usage,
|
||||
identified the animated `borderangle` loop as the culprit; added mako
|
||||
notifications and waybar modules.
|
||||
- **Monitor management** (`session-ses_ffc9.md`): adopted
|
||||
[monique](https://github.com/notwidow/monique) for arranging multiple
|
||||
monitors, including clamshell mode and the `hypr-lid-power` service
|
||||
(`hyprland/.config/systemd/user/hypr-lid-power.service`).
|
||||
- **Cloudflare tunnel + secrets** (`session-ses_0098.md`): wired the
|
||||
`cloudflared-k8s` service to pull the Cloudflare Access service token from
|
||||
the Homelab 1Password vault at runtime via `op run` — it is never written to
|
||||
disk.
|
||||
|
||||
## Rules for agents
|
||||
|
||||
1. **Never commit secrets.** No API keys, tokens, passwords, or private keys
|
||||
may be committed. Use 1Password references (`op://Vault/Item/...`) and
|
||||
inject at runtime with `op run -- ...`. `.secrets.baseline` + `detect-secrets`
|
||||
(via pre-commit) is the guardrail; keep it updated (`detect-secrets scan`
|
||||
and re-baseline if a benign false positive is added).
|
||||
2. **Fit every change into the stow layout.** Config files must live under a
|
||||
package directory mirroring their destination (e.g. a new app config goes
|
||||
under `<pkg>/.config/<app>/`). After changes, the package must be
|
||||
committable and stowable (`make link` / `make unlink` must keep working).
|
||||
3. **`resources/` is untracked and must stay untracked.** Session transcripts
|
||||
under `resources/ai/sessions/` can contain sensitive values (e.g. a
|
||||
Cloudflare client secret shown during a session). Do not stage, add, or
|
||||
commit anything under `resources/`. Note `wluma/` is likewise local-only.
|
||||
4. **Hyprland config is Lua, not hyprlang.** All `hyprland/.config/hypr/`
|
||||
configs are `.lua` files driven by `hyprland.lua`. Do not reintroduce
|
||||
`.conf`/hyprlang syntax.
|
||||
5. **`nvim/` is a private submodule** pointing at a self-hosted Gitea/GitLab
|
||||
repo; never replace it with a public fork and don't commit submodule state
|
||||
changes unless intended. Pull with `make pull-updates`.
|
||||
6. **Behave like the user's own assistant on this machine.** These dotfiles
|
||||
reference real hosts (`sams_laptop`, `k8s.samoneal.io`, `git-ssh.samoneal.io`)
|
||||
and real 1Password vaults — work with them, but keep the repo portable by
|
||||
leaving secrets and machine-specific absolute paths in comments rather than
|
||||
committed values where practical.
|
||||
7. **Verify before finishing.** Run `git status`/`git diff` to confirm only
|
||||
intended files changed and nothing sensitive is staged. If unsure whether a
|
||||
value is a secret, treat it as one.
|
||||
|
||||
## Workflow
|
||||
|
||||
- Pre-commit hooks: `pre-commit install` (runs trailing-whitespace +
|
||||
detect-secrets).
|
||||
- Lint/typecheck: this repo is plain config + shell; shell scripts should stay
|
||||
`sh`/`bash`-compatible and pass `shellcheck` if available.
|
||||
- Record substantial AI sessions: if a session materially changes this repo,
|
||||
save the transcript under `resources/ai/sessions/` (keep it untracked).
|
||||
@@ -1,6 +1,6 @@
|
||||
HOME_TARGET ?= $(HOME)
|
||||
SYSTEM_DIRS := etc usr var opt boot
|
||||
PACKAGES := $(patsubst %/,%,$(wildcard */))
|
||||
PACKAGES := $(filter-out resources wluma,$(patsubst %/,%,$(wildcard */)))
|
||||
|
||||
.PHONY: check-stow pull-updates unlink link
|
||||
|
||||
@@ -77,10 +77,10 @@ link: check-stow
|
||||
done; \
|
||||
if [ "$$is_sys" -eq 1 ]; then \
|
||||
echo " [System] Stowing $$pkg/$$sub to $$sub"; \
|
||||
sudo stow -d "$$pkg" -t "/$$sub" "$$sub"; \
|
||||
sudo stow --restow -d "$$pkg" -t "/$$sub" "$$sub"; \
|
||||
else \
|
||||
echo " [USER] Stowing $$pkg/$$sub to $(HOME_TARGET)/$$sub"; \
|
||||
stow -d "$$pkg" -t "$(HOME_TARGET)/$$sub" "$$sub"; \
|
||||
stow --restow -d "$$pkg" -t "$(HOME_TARGET)/$$sub" "$$sub"; \
|
||||
fi; \
|
||||
done; \
|
||||
done
|
||||
|
||||
@@ -1,14 +1,80 @@
|
||||
# Dotfiles
|
||||
|
||||
All the configuration files for my current machine setup.
|
||||
All the configuration files for my current machine setup. Managed with GNU
|
||||
stow so every package maps directly onto the relevant `~/.config`, `~/.local`,
|
||||
`/etc`, etc. paths.
|
||||
|
||||
## Configurations
|
||||
## Requirements
|
||||
|
||||
- Ghostty
|
||||
- Hyprland
|
||||
- Local
|
||||
- Monique
|
||||
- NVIM
|
||||
- SSH
|
||||
- SystemD
|
||||
- ZSH
|
||||
- [GNU stow](https://www.gnu.org/software/stow/)
|
||||
- `make`
|
||||
- [op (1Password CLI)](https://developer.1password.com/docs/cli/) for anything
|
||||
that needs a secret
|
||||
|
||||
## Quick start
|
||||
|
||||
```sh
|
||||
# Install stow if missing (auto-detects Arch/Debian/macOS)
|
||||
make check-stow
|
||||
|
||||
# Link every package into $HOME (system dirs like /etc are stowed with sudo)
|
||||
make link
|
||||
|
||||
# Unlink everything again
|
||||
make unlink
|
||||
|
||||
# Pull main plus submodules
|
||||
make pull-updates
|
||||
```
|
||||
|
||||
## Packages
|
||||
|
||||
| Package | Path | Description |
|
||||
| ----------- | -------------- | ------------------------------------------------------- |
|
||||
| `backgrounds` | `~/.config/backgrounds` | Wallpaper collection (incl. Dynamic-Wallpapers) |
|
||||
| `ghostty` | `~/.config/ghostty` | Ghostty terminal config |
|
||||
| `hosts` | `~/.config/hosts` | Custom `HOSTALIASES` file (`HOSTALIASES=~/.config/hosts`) |
|
||||
| `hyprland` | `~/.config/hypr`, `~/.local/bin` | Hyprland config (Lua), scripts, `hypr-lid-power` service |
|
||||
| `hyprlock` | `~/.config/hypr` | Lockscreen config |
|
||||
| `hyprmocha` | `~/.config/hypr` | Catppuccin Mocha palette as Lua |
|
||||
| `hyprpaper` | `~/.config/hypr` | Wallpaper daemon config |
|
||||
| `hyprshell` | `~/.config/hyprshell` | Launcher/overview (Rust, RON config + CSS) |
|
||||
| `local` | `~/.local/bin` | Local scripts (e.g. `fetch-nas-credentials.sh`) |
|
||||
| `mako` | `~/.config/mako` | Notifications |
|
||||
| `monique` | `~/.config/monique` | Monitor/clamshell arrangement |
|
||||
| `nvim` | `~/.config/nvim` | Git submodule (private repo) |
|
||||
| `rofi` | `~/.config/rofi` | Launcher (Catppuccin Mocha) |
|
||||
| `ssh` | `~/.ssh/config` | SSH config (1Password agent + cloudflared proxy) |
|
||||
| `sunsetr` | `~/.config/sunsetr` | Screen color temperature (`geo.toml` is gitignored) |
|
||||
| `systemd` | `~/.config/systemd/user`, `/etc/systemd` | User + system units (cloudflared, rclone/GDrive, NAS mounts, 1Password sign-in) |
|
||||
| `waybar` | `~/.config/waybar` | Top bar |
|
||||
| `wofi` | `~/.config/wofi` | App menu |
|
||||
| `yay` | `~/.config/yay` | AUR helper config |
|
||||
| `zsh` | `~/.zshrc` | Zsh config |
|
||||
|
||||
`wluma/` and `resources/` exist locally but are **not** committed (see
|
||||
`AGENTS.md`).
|
||||
|
||||
## Secrets management
|
||||
|
||||
No secrets are committed to this repo. Anything secret goes through
|
||||
[1Password](https://1password.com):
|
||||
|
||||
- References look like `op://Vault/Item/field[/section]` (e.g. the Cloudflare
|
||||
service token in `systemd/.config/systemd/user/cloudflared-k8s.service`).
|
||||
- Services inject secrets at runtime with `op run -- ...`, so values never hit
|
||||
disk or git.
|
||||
- `fetch-nas-credentials.sh` writes fetched NAS credentials to
|
||||
`~/.nas/.smbcredentials` (chmod 600) at boot.
|
||||
- `detect-secrets` runs via `pre-commit` against `.secrets.baseline`.
|
||||
|
||||
## Submodules
|
||||
|
||||
- `nvim/.config/nvim` → `git@git-ssh.samoneal.io:2222/sam_oneal/nvim-config.git`
|
||||
(private). Pull with `make pull-updates`.
|
||||
|
||||
## AI assistance
|
||||
|
||||
This repo is developed with AI assistance. See `AGENTS.md` for how AI has been
|
||||
used, the conventions it must follow, and where session transcripts are kept
|
||||
(`resources/ai/sessions/`).
|
||||
|
||||
@@ -1,71 +1,118 @@
|
||||
-- See https://wiki.hypr.land/Configuring/Basics/Binds/ for more
|
||||
|
||||
-- Sound through pactl
|
||||
hl.bind("XF86AudioRaiseVolume", hl.dsp.exec_cmd("pactl set-sink-volume @DEFAULT_SINK@ +10%"))
|
||||
hl.bind("XF86AudioLowerVolume", hl.dsp.exec_cmd("pactl set-sink-volume @DEFAULT_SINK@ -10%"))
|
||||
hl.bind("XF86AudioMute", hl.dsp.exec_cmd("pactl set-sink-mute @DEFAULT_SINK@ toggle"))
|
||||
hl.bind("XF86AudioPlay", hl.dsp.exec_cmd("playerctl play-pause"))
|
||||
hl.bind("XF86AudioPrev", hl.dsp.exec_cmd("playerctl previous"))
|
||||
hl.bind("XF86AudioNext", hl.dsp.exec_cmd("playerctl next"))
|
||||
hl.bind("XF86AudioRaiseVolume", hl.dsp.exec_cmd("pactl set-sink-volume @DEFAULT_SINK@ +10%"), { desc = "Raise volume" })
|
||||
hl.bind("XF86AudioLowerVolume", hl.dsp.exec_cmd("pactl set-sink-volume @DEFAULT_SINK@ -10%"), { desc = "Lower volume" })
|
||||
hl.bind("XF86AudioMute", hl.dsp.exec_cmd("pactl set-sink-mute @DEFAULT_SINK@ toggle"), { desc = "Mute audio" })
|
||||
hl.bind("XF86AudioPlay", hl.dsp.exec_cmd("playerctl play-pause"), { desc = "Play/pause media" })
|
||||
hl.bind("XF86AudioPrev", hl.dsp.exec_cmd("playerctl previous"), { desc = "Previous track" })
|
||||
hl.bind("XF86AudioNext", hl.dsp.exec_cmd("playerctl next"), { desc = "Next track" })
|
||||
|
||||
-- Brightness through brightnessctl
|
||||
hl.bind("XF86MonBrightnessUp", hl.dsp.exec_cmd("brightnessctl set +5%"))
|
||||
hl.bind("XF86MonBrightnessDown", hl.dsp.exec_cmd("brightnessctl set 5%-"))
|
||||
hl.bind("XF86MonBrightnessUp", hl.dsp.exec_cmd("brightnessctl set +5%"), { desc = "Increase brightness" })
|
||||
hl.bind("XF86MonBrightnessDown", hl.dsp.exec_cmd("brightnessctl set 5%-"), { desc = "Decrease brightness" })
|
||||
|
||||
-- Main modifier binds
|
||||
hl.bind(mainMod .. " + T", hl.dsp.exec_cmd(terminal))
|
||||
hl.bind(mainMod .. " + B", hl.dsp.exec_cmd(browser))
|
||||
hl.bind(mainMod .. " + F", hl.dsp.exec_cmd(fileManager))
|
||||
hl.bind(mainMod .. " + C", hl.dsp.window.kill())
|
||||
hl.bind(mainMod .. " + M", hl.dsp.exit())
|
||||
hl.bind(mainMod .. " + V", hl.dsp.window.float({ action = "toggle" }))
|
||||
hl.bind(mainMod .. " + space", hl.dsp.exec_cmd(menu))
|
||||
hl.bind(SUPER_SHIFT .. " + L", hl.dsp.exec_cmd("hyprlock"))
|
||||
hl.bind(SUPER_SHIFT .. " + R", hl.dsp.exec_cmd("hyprctl reload"))
|
||||
hl.bind(mainMod .. " + T", hl.dsp.exec_cmd(terminal), { desc = "Open terminal" })
|
||||
hl.bind(mainMod .. " + B", hl.dsp.exec_cmd(browser), { desc = "Open browser" })
|
||||
hl.bind(mainMod .. " + F", hl.dsp.exec_cmd(fileManager), { desc = "Open file manager" })
|
||||
hl.bind(mainMod .. " + C", hl.dsp.window.close(), { desc = "Close active window" })
|
||||
hl.bind(mainMod .. " + Q", hl.dsp.exec_cmd("hyprctl dispatch closewindow \"class:$(hyprctl activewindow -j | jq -r .class)\""), { desc = "Close active window (by class)" })
|
||||
hl.bind(mainMod .. " + M", hl.dsp.exit(), { desc = "Exit Hyprland" })
|
||||
hl.bind(mainMod .. " + V", hl.dsp.window.float({ action = "toggle" }), { desc = "Toggle floating" })
|
||||
hl.bind(mainMod .. " + space", hl.dsp.exec_cmd(menu), { desc = "Open app menu" })
|
||||
hl.bind(SUPER_SHIFT .. " + L", hl.dsp.exec_cmd("hyprlock"), { desc = "Lock screen" })
|
||||
hl.bind(SUPER_SHIFT .. " + R", hl.dsp.exec_cmd("hyprctl reload"), { desc = "Reload config" })
|
||||
-- Monique: GUI monitor arrangement/display settings
|
||||
hl.bind(SUPER_SHIFT .. " + M", hl.dsp.exec_cmd("monique"))
|
||||
hl.bind(SUPER_SHIFT .. " + D", hl.dsp.exec_cmd("hyprctl keyword monitor eDP-1, disable"))
|
||||
hl.bind(SUPER_SHIFT .. " + F", hl.dsp.exec_cmd("hyprctl keyword monitor eDP-1, enable"))
|
||||
hl.bind(SUPER_SHIFT .. " + M", hl.dsp.exec_cmd("monique"), { desc = "Open monique (monitor settings)" })
|
||||
hl.bind(SUPER_SHIFT .. " + D", hl.dsp.exec_cmd("hyprctl keyword monitor eDP-1, disable"), { desc = "Disable eDP-1 (clamshell)" })
|
||||
hl.bind(SUPER_SHIFT .. " + F", hl.dsp.exec_cmd("hyprctl keyword monitor eDP-1, enable"), { desc = "Enable eDP-1" })
|
||||
|
||||
-- Screenshots
|
||||
hl.bind("Print", hl.dsp.exec_cmd("grim -c -o \"$(hyprctl activeworkspace -j | jq -r '.monitor')\" $(xdg-user-dir PICTURES)/Screenshots/$(date +'%s_grim.png')"))
|
||||
hl.bind("SHIFT + Print", hl.dsp.exec_cmd("grim -g \"$(slurp)\" $(xdg-user-dir PICTURES)/Screenshots/$(date +'%s_grim.png')"))
|
||||
hl.bind("Print", hl.dsp.exec_cmd("grim -c -o \"$(hyprctl activeworkspace -j | jq -r '.monitor')\" $(xdg-user-dir PICTURES)/Screenshots/$(date +'%s_grim.png')"), { desc = "Screenshot active monitor" })
|
||||
hl.bind("SHIFT + Print", hl.dsp.exec_cmd("grim -g \"$(slurp)\" $(xdg-user-dir PICTURES)/Screenshots/$(date +'%s_grim.png')"), { desc = "Screenshot region" })
|
||||
|
||||
-- Dwindle layout
|
||||
hl.bind(mainMod .. " + P", hl.dsp.window.pseudo()) -- dwindle
|
||||
hl.bind(mainMod .. " + E", hl.dsp.layout("togglesplit")) -- dwindle
|
||||
hl.bind(mainMod .. " + CTRL + F", hl.dsp.window.fullscreen({ action = "toggle" })) -- dwindle
|
||||
hl.bind(mainMod .. " + W", hl.dsp.group.toggle()) -- dwindle
|
||||
hl.bind(mainMod .. " + P", hl.dsp.window.pseudo(), { desc = "Toggle pseudo tiling" }) -- dwindle
|
||||
hl.bind(mainMod .. " + E", hl.dsp.layout("togglesplit"), { desc = "Toggle split" }) -- dwindle
|
||||
hl.bind(mainMod .. " + CTRL + F", hl.dsp.window.fullscreen({ action = "toggle" }), { desc = "Toggle fullscreen" }) -- dwindle
|
||||
hl.bind(mainMod .. " + W", hl.dsp.group.toggle(), { desc = "Toggle window group" }) -- dwindle
|
||||
|
||||
-- Move focus with mainMod + vim keys
|
||||
hl.bind(mainMod .. " + H", hl.dsp.focus({ direction = "l" }))
|
||||
hl.bind(mainMod .. " + L", hl.dsp.focus({ direction = "r" }))
|
||||
hl.bind(mainMod .. " + K", hl.dsp.focus({ direction = "u" }))
|
||||
hl.bind(mainMod .. " + J", hl.dsp.focus({ direction = "d" }))
|
||||
hl.bind(mainMod .. " + H", hl.dsp.focus({ direction = "l" }), { desc = "Focus left" })
|
||||
hl.bind(mainMod .. " + L", hl.dsp.focus({ direction = "r" }), { desc = "Focus right" })
|
||||
hl.bind(mainMod .. " + K", hl.dsp.focus({ direction = "u" }), { desc = "Focus up" })
|
||||
hl.bind(mainMod .. " + J", hl.dsp.focus({ direction = "d" }), { desc = "Focus down" })
|
||||
|
||||
-- Cycle workspaces on the active monitor with mainMod + arrows. Advancing past
|
||||
-- the last workspace on the monitor creates a fresh (empty) workspace there;
|
||||
-- going before the first wraps around to the last one on the monitor.
|
||||
local function step_workspace(dir)
|
||||
local mon = hl.get_active_monitor()
|
||||
if not mon then return end
|
||||
local current = mon.active_workspace.id
|
||||
|
||||
local mon_ids, all_max = {}, 0
|
||||
for _, ws in ipairs(hl.get_workspaces()) do
|
||||
if ws.id > all_max then all_max = ws.id end
|
||||
if ws.monitor and ws.monitor.id == mon.id then
|
||||
table.insert(mon_ids, ws.id)
|
||||
end
|
||||
end
|
||||
table.sort(mon_ids)
|
||||
|
||||
local target
|
||||
if dir > 0 then
|
||||
for _, id in ipairs(mon_ids) do
|
||||
if id > current then target = id break end
|
||||
end
|
||||
-- No next workspace on this monitor: create one right here.
|
||||
if not target then target = all_max + 1 end
|
||||
else
|
||||
for i = #mon_ids, 1, -1 do
|
||||
if mon_ids[i] < current then target = mon_ids[i] break end
|
||||
end
|
||||
-- No previous workspace on this monitor: wrap to the last one.
|
||||
if not target and #mon_ids > 0 then target = mon_ids[#mon_ids] end
|
||||
end
|
||||
|
||||
if target then hl.dispatch(hl.dsp.focus({ workspace = target })) end
|
||||
end
|
||||
|
||||
hl.bind(mainMod .. " + Left", function() step_workspace(-1) end, { desc = "Previous workspace (active monitor)" })
|
||||
hl.bind(mainMod .. " + Right", function() step_workspace(1) end, { desc = "Next workspace (active monitor); creates one past the end" })
|
||||
|
||||
-- Switch workspaces with mainMod + [0-9]
|
||||
for i = 1, 10 do
|
||||
local key = i % 10 -- 10 maps to key 0
|
||||
hl.bind(mainMod .. " + " .. key, hl.dsp.focus({ workspace = i }))
|
||||
hl.bind(mainMod .. " + " .. key, hl.dsp.focus({ workspace = i }), { desc = "Go to workspace " .. i })
|
||||
end
|
||||
|
||||
-- Move active window to a workspace with mainMod + SHIFT + [0-9]
|
||||
for i = 1, 10 do
|
||||
local key = i % 10 -- 10 maps to key 0
|
||||
hl.bind(mainMod .. " + SHIFT + " .. key, hl.dsp.window.move({ workspace = i }))
|
||||
hl.bind(mainMod .. " + SHIFT + " .. key, hl.dsp.window.move({ workspace = i }), { desc = "Move window to workspace " .. i })
|
||||
end
|
||||
|
||||
-- Example special workspace (scratchpad)
|
||||
hl.bind(mainMod .. " + S", hl.dsp.workspace.toggle_special("magic"))
|
||||
hl.bind(mainMod .. " + SHIFT + S", hl.dsp.window.move({ workspace = "special:magic" }))
|
||||
hl.bind(mainMod .. " + S", hl.dsp.workspace.toggle_special("magic"), { desc = "Toggle scratchpad" })
|
||||
hl.bind(mainMod .. " + SHIFT + S", hl.dsp.window.move({ workspace = "special:magic" }), { desc = "Move window to scratchpad" })
|
||||
|
||||
-- Scroll through existing workspaces with mainMod + scroll
|
||||
hl.bind(mainMod .. " + mouse_down", hl.dsp.focus({ workspace = "e+1" }))
|
||||
hl.bind(mainMod .. " + mouse_up", hl.dsp.focus({ workspace = "e-1" }))
|
||||
hl.bind(mainMod .. " + mouse_down", hl.dsp.focus({ workspace = "e+1" }), { desc = "Next workspace (scroll)" })
|
||||
hl.bind(mainMod .. " + mouse_up", hl.dsp.focus({ workspace = "e-1" }), { desc = "Previous workspace (scroll)" })
|
||||
|
||||
-- Keybind cheat sheet
|
||||
hl.bind(SUPER_SHIFT .. " + H", hl.dsp.exec_cmd("binds-help.sh"), { desc = "Keybind cheat sheet" })
|
||||
|
||||
-- Workspace overview (macOS Mission Control style). SUPER + Up is registered by
|
||||
-- the hyprshell daemon itself ("Open Overview with Super + Up"); SUPER + Down
|
||||
-- closes the overview again without switching.
|
||||
hl.bind(mainMod .. " + Down", hl.dsp.exec_cmd("overview-close.sh"), { desc = "Close workspace overview" })
|
||||
|
||||
-- Move/resize windows with mainMod + LMB/RMB and dragging
|
||||
hl.bind(mainMod .. " + mouse:272", hl.dsp.window.drag(), { mouse = true })
|
||||
hl.bind(mainMod .. " + mouse:273", hl.dsp.window.resize(), { mouse = true })
|
||||
hl.bind(mainMod .. " + mouse:272", hl.dsp.window.drag(), { mouse = true, desc = "Drag window" })
|
||||
hl.bind(mainMod .. " + mouse:273", hl.dsp.window.resize(), { mouse = true, desc = "Resize window" })
|
||||
|
||||
-- Laptop lid is handled by hypr-lid-power.service (delayed lock/suspend when
|
||||
-- closed undocked; display/clamshell handling is done by moniqued) instead of
|
||||
|
||||
@@ -2,3 +2,7 @@
|
||||
hl.env("XCURSOR_SIZE", "24")
|
||||
hl.env("QT_QPA_PLATFORMTHEME", "qt5ct") -- change to qt6ct if you have that
|
||||
hl.env("SUDO_ASKPASS", os.getenv("HOME") .. "/.local/bin/sudo-askpass.sh")
|
||||
-- Prepend ~/.local/bin so `hyprlock` (and other user scripts) resolve to the
|
||||
-- crash-guard wrapper instead of /usr/bin/hyprlock. Hyprland's exec/keybind
|
||||
-- PATH is otherwise the system PATH and misses user-local binaries.
|
||||
hl.env("PATH", os.getenv("HOME") .. "/.local/bin:" .. (os.getenv("PATH") or "/usr/bin:/bin"))
|
||||
|
||||
@@ -23,14 +23,26 @@ listener {
|
||||
on-timeout = loginctl lock-session # lock screen when timeout has passed
|
||||
}
|
||||
|
||||
# The dpms-off and suspend listeners ignore idle inhibitors (Steam, browsers,
|
||||
# etc. hold them) so the screen still blanks and the machine still suspends
|
||||
# after the screen is locked -- otherwise a held inhibitor would keep the
|
||||
# locked screen on forever. `condition_cmd` gates them on the lock screen
|
||||
# actually running, so inhibitors keep working as intended while unlocked
|
||||
# (e.g. a video keeps the screen awake).
|
||||
listener {
|
||||
timeout = 330 # 5.5min
|
||||
ignore_inhibit = true # fire even while apps hold idle inhibitors
|
||||
condition_cmd = pidof hyprlock > /dev/null # ...but only once the session is locked
|
||||
condition_retry = 30 # if not locked yet, re-check every 30s while idle
|
||||
on-timeout = hyprctl dispatch dpms off # screen off when timeout has passed
|
||||
on-resume = hyprctl dispatch dpms on && brightnessctl -r # screen on when activity is detected after timeout has fired.
|
||||
}
|
||||
|
||||
listener {
|
||||
timeout = 1800 # 30min
|
||||
ignore_inhibit = true # fire even while apps hold idle inhibitors
|
||||
condition_cmd = pidof hyprlock > /dev/null # ...but only while the session is locked
|
||||
condition_retry = 60 # if not locked yet, re-check every 60s while idle
|
||||
on-timeout = systemctl suspend # suspend pc
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,14 @@ hl.config({
|
||||
},
|
||||
})
|
||||
|
||||
hl.config({
|
||||
binds = {
|
||||
-- Let SUPER+scroll workspace cycling wrap around instead of stopping at
|
||||
-- the edges. (SUPER+Left/Right wrapping is handled directly in binds.lua.)
|
||||
allow_workspace_cycles = true,
|
||||
},
|
||||
})
|
||||
|
||||
hl.config({
|
||||
decoration = {
|
||||
rounding = 4,
|
||||
@@ -94,6 +102,9 @@ hl.config({
|
||||
mouse_move_focuses_monitor = false,
|
||||
-- Skip drawing the Hyprland logo in the corner of empty workspaces.
|
||||
disable_hyprland_logo = true,
|
||||
-- Allow a new hyprlock to take over the lock after a crash; without this a
|
||||
-- dead lock client leaves the session permanently locked (no lockscreen).
|
||||
allow_session_lock_restore = true,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -103,5 +114,8 @@ hl.config({
|
||||
hl.config({
|
||||
debug = {
|
||||
vfr = true,
|
||||
-- Temporarily on to diagnose the mystery re-lock (disable_logs=true
|
||||
-- default hides dispatch exec lines from hyprland.log).
|
||||
disable_logs = false,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
-- Managed by monique (run `monique` or SUPER+SHIFT+M to arrange). The built-in
|
||||
-- panel is managed at runtime by moniqued's clamshell mode: enabled here, then
|
||||
-- disabled while the lid is closed with external displays attached.
|
||||
-- See https://wiki.hypr.land/Configuring/Basics/Monitors/ for more
|
||||
hl.monitor({ output = "desc:BOE 0x0BC9", mode = "preferred", position = "0x0", scale = 1.0 })
|
||||
hl.monitor({ output = "desc:Viewteck Co. Ltd. GNV34DB", mode = "3440x1440@50.0", position = "3795x1785", scale = 1.0 })
|
||||
hl.monitor({ output = "desc:Dell Inc. DELL U2515HX GMDK46C4053L", mode = "2560x1440@59.95", position = "5488x345", scale = 1.0 })
|
||||
hl.monitor({ output = "desc:Dell Inc. DELL U2518D 0WG2J9C5B3WL", mode = "2560x1440@59.95", position = "2928x345", scale = 1.0 })
|
||||
-- Generated by Monique - https://github.com/ToRvaLDz/monique
|
||||
|
||||
hl.monitor({
|
||||
output = "desc:BOE 0x0BC9",
|
||||
mode = "2560x1600@165",
|
||||
position = "0x0",
|
||||
scale = 1,
|
||||
cm = "srgb",
|
||||
sdr_min_luminance = 0.2,
|
||||
sdr_max_luminance = 80,
|
||||
})
|
||||
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
# Searchable cheat sheet of Hyprland keybindings, shown in wofi.
|
||||
#
|
||||
# The descriptions shown here come from the `desc` option passed to hl.bind()
|
||||
# in ~/.config/hypr/binds.lua, read back at runtime via `hyprctl binds -j`,
|
||||
# so the cheat sheet always matches the live config.
|
||||
set -u
|
||||
|
||||
mods_from_mask() {
|
||||
local mask="$1" out=""
|
||||
(( mask & 1 )) && out="${out:+$out + }SHIFT"
|
||||
(( mask & 4 )) && out="${out:+$out + }CTRL"
|
||||
(( mask & 8 )) && out="${out:+$out + }ALT"
|
||||
(( mask & 64 )) && out="${out:+$out + }SUPER"
|
||||
(( mask & 128 )) && out="${out:+$out + }MOD5"
|
||||
printf "%s" "$out"
|
||||
}
|
||||
|
||||
hyprctl binds -j |
|
||||
jq -rc '.[] | select(.has_description) | select(.description != "") | [.modmask, .key, .description] | @tsv' |
|
||||
while IFS=$'\t' read -r mask key desc; do
|
||||
if (( mask )); then
|
||||
mods="$(mods_from_mask "$mask")"
|
||||
printf '%s + %s\t%s\n' "$mods" "$key" "$desc"
|
||||
else
|
||||
printf '%s\t%s\n' "$key" "$desc"
|
||||
fi
|
||||
done |
|
||||
sort -k1,1 |
|
||||
column -t -s $'\t' |
|
||||
wofi --dmenu --prompt "Hyprland keybinds" >/dev/null
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
# macOS-style SUPER+Down: close the hyprshell workspace overview if it is open,
|
||||
# returning to the current workspace without switching.
|
||||
#
|
||||
# hyprshell's overview is a gtk4-layer-shell surface whose namespace is
|
||||
# "hyprshell_overview", and the OpenOverview IPC message toggles the overview
|
||||
# closed when it is already open (see OverviewRootInput::OpenOverview).
|
||||
set -u
|
||||
|
||||
if ! hyprctl layers -j | jq -e '
|
||||
.. | objects | .namespace? // empty | select(. == "hyprshell_overview")
|
||||
' >/dev/null; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
hyprshell socat '"OpenOverview"'
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env bash
|
||||
# Print the current weather as a short icon+temp string, e.g. "🌦️ +83°F".
|
||||
# Caches the wttr.in response for CACHE_MAX_AGE seconds so the lock screen and
|
||||
# waybar don't hit the network on every refresh. Override the location with
|
||||
# WEATHER_CITY or edit CITY below.
|
||||
set -u
|
||||
|
||||
CITY="${WEATHER_CITY:-Denver}"
|
||||
CACHE_DIR="${XDG_RUNTIME_DIR:-/tmp}"
|
||||
CACHE="${CACHE_DIR}/wttr.cache"
|
||||
CACHE_MAX_AGE=1800 # 30 minutes
|
||||
URL="https://wttr.in/${CITY}?format=%c+%t"
|
||||
|
||||
cache_age() {
|
||||
[ -f "${CACHE}" ] || return 1
|
||||
now=$(date +%s)
|
||||
mtime=$(stat -c %Y "${CACHE}")
|
||||
[ "$(( now - mtime ))" -lt "${CACHE_MAX_AGE}" ]
|
||||
}
|
||||
|
||||
if cache_age; then
|
||||
cat "${CACHE}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TMP="${CACHE}.tmp.$$"
|
||||
if curl -fsS --max-time 10 "${URL}" > "${TMP}" 2>/dev/null; then
|
||||
mv "${TMP}" "${CACHE}"
|
||||
cat "${CACHE}"
|
||||
else
|
||||
rm -f "${TMP}" || true
|
||||
# Offline: fall back to whatever we cached last, even if stale.
|
||||
[ -f "${CACHE}" ] && cat "${CACHE}"
|
||||
fi
|
||||
@@ -7,14 +7,17 @@ $font = JetBrainsMono Nerd Font
|
||||
|
||||
# General
|
||||
general {
|
||||
disable_loading_bar = false
|
||||
hide_cursor = false
|
||||
}
|
||||
|
||||
# Authentication
|
||||
# Fingerprint is disabled: GDM's login worker (pam/gdm-fingerprint) holds the
|
||||
# device for the whole session, so hyprlock can never claim it -- the failed
|
||||
# claim blocked the auth thread and made unlocks appear stuck. Fingerprint is
|
||||
# still available at the GDM login screen; hyprlock is password-only.
|
||||
auth {
|
||||
fingerprint {
|
||||
enabled = true
|
||||
enabled = false
|
||||
ready_message = Scan fingerprint to unlock
|
||||
present_message = Scanning...
|
||||
retry_delay = 250 # in milliseconds
|
||||
@@ -45,7 +48,7 @@ label {
|
||||
# Date
|
||||
label {
|
||||
monitor =
|
||||
text = cmd[update:43200000] echo "$(date + "%A, %d %B %Y")"
|
||||
text = cmd[update:43200000] echo "$(date +'%A, %d %B %Y')"
|
||||
color = $text
|
||||
font_size = 25
|
||||
font_family = $font
|
||||
@@ -54,6 +57,30 @@ label {
|
||||
valign = top
|
||||
}
|
||||
|
||||
# Battery
|
||||
label {
|
||||
monitor =
|
||||
text = cmd[update:60000] $HOME/.local/bin/hyprlock-battery.sh
|
||||
color = $subtext1
|
||||
font_size = 20
|
||||
font_family = $font
|
||||
position = -30, -190
|
||||
halign = right
|
||||
valign = top
|
||||
}
|
||||
|
||||
# Weather
|
||||
label {
|
||||
monitor =
|
||||
text = cmd[update:600000] $HOME/.local/bin/weather.sh
|
||||
color = $subtext1
|
||||
font_size = 20
|
||||
font_family = $font
|
||||
position = -30, -215
|
||||
halign = right
|
||||
valign = top
|
||||
}
|
||||
|
||||
# User Avatar
|
||||
image {
|
||||
monitor =
|
||||
@@ -66,6 +93,18 @@ image {
|
||||
valign = center
|
||||
}
|
||||
|
||||
# Notifications (latest mako notification; empty when none)
|
||||
label {
|
||||
monitor =
|
||||
text = cmd[update:5000] $HOME/.local/bin/hyprlock-notifications.sh
|
||||
color = $subtext0
|
||||
font_size = 16
|
||||
font_family = $font
|
||||
position = 0, 60
|
||||
halign = center
|
||||
valign = bottom
|
||||
}
|
||||
|
||||
# Input Field
|
||||
input-field {
|
||||
monitor =
|
||||
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
# Guard wrapper for hyprlock (0.9.x): upstream has crashes on DPMS-off / monitor
|
||||
# power transitions while the lock screen is running (hyprlock#991, #953, #695).
|
||||
# If the real hyprlock dies, this restarts it so the session doesn't end up in a
|
||||
# "lockscreen app died" state. Requires misc:allow_session_lock_restore = true
|
||||
# in Hyprland config for the replacement lock to be accepted.
|
||||
|
||||
set -u
|
||||
|
||||
REAL_HYPRLOCK=/usr/bin/hyprlock
|
||||
MAX_RESTARTS=20
|
||||
|
||||
restart=0
|
||||
while true; do
|
||||
"$REAL_HYPRLOCK" "$@"
|
||||
code=$?
|
||||
|
||||
# 0: exited cleanly (e.g. unlocked) -- done.
|
||||
# 1: auth failed, retry -- let the loop back off and try again.
|
||||
if [ "$code" -eq 0 ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
restart=$((restart + 1))
|
||||
if [ "$restart" -ge "$MAX_RESTARTS" ]; then
|
||||
exit "$code"
|
||||
fi
|
||||
|
||||
# Brief pause so a crash loop doesn't burn CPU (fade back in quickly).
|
||||
sleep 0.5
|
||||
done
|
||||
Executable
+39
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
# Battery status for the hyprlock screen, e.g. " 18%".
|
||||
# Uses the first battery found under /sys/class/power_supply (BAT0/BAT1, ...);
|
||||
# prints nothing on desktops without a battery.
|
||||
set -u
|
||||
|
||||
bat=""
|
||||
for b in /sys/class/power_supply/BAT*; do
|
||||
if [ -r "${b}/capacity" ]; then
|
||||
bat="${b}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
[ -z "${bat}" ] && exit 0
|
||||
|
||||
cap="$(cat "${bat}/capacity" 2>/dev/null || echo 0)"
|
||||
status="$(cat "${bat}/status" 2>/dev/null || echo Unknown)"
|
||||
|
||||
case "${status}" in
|
||||
Charging|Full)
|
||||
icon=""
|
||||
;;
|
||||
*)
|
||||
if [ "${cap}" -ge 80 ]; then
|
||||
icon=""
|
||||
elif [ "${cap}" -ge 60 ]; then
|
||||
icon=""
|
||||
elif [ "${cap}" -ge 40 ]; then
|
||||
icon=""
|
||||
elif [ "${cap}" -ge 20 ]; then
|
||||
icon=""
|
||||
else
|
||||
icon=""
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
printf '%s %s%%' "${icon}" "${cap}"
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
# Latest mako notification for the hyprlock screen, Pango-escaped, e.g.
|
||||
# "Battery test: Battery at 18%". Prints nothing when there are no
|
||||
# notifications, so the label renders empty.
|
||||
set -u
|
||||
|
||||
makoctl list -j 2>/dev/null | jq -r '
|
||||
if length == 0 then
|
||||
empty
|
||||
else
|
||||
.[-1] as $n |
|
||||
(if $n.app_name != null and $n.app_name != "" then $n.app_name + ": " else "" end) +
|
||||
($n.summary // "") +
|
||||
(if $n.body != null and $n.body != "" then " — " + $n.body[0:80] else "" end)
|
||||
end' 2>/dev/null | sed 's/&/\&/g; s/</\</g; s/>/\>/g'
|
||||
@@ -1,6 +1,6 @@
|
||||
// Edit with `hyprshell config edit`
|
||||
(
|
||||
version: 3,
|
||||
version: 4,
|
||||
windows: (
|
||||
scale: 8.5,
|
||||
items_per_row: 5,
|
||||
@@ -43,7 +43,6 @@
|
||||
actions: (
|
||||
actions: [
|
||||
lock_screen,
|
||||
hibernate,
|
||||
logout,
|
||||
reboot,
|
||||
shutdown,
|
||||
@@ -69,11 +68,13 @@
|
||||
),
|
||||
),
|
||||
),
|
||||
key: "Tab",
|
||||
modifier: "alt",
|
||||
filter_by: [],
|
||||
hide_filtered: false,
|
||||
exclude_special_workspaces: "",
|
||||
key: "Up",
|
||||
top_offset: 430,
|
||||
modifier: "super",
|
||||
filter_by: [
|
||||
current_monitor,
|
||||
],
|
||||
exclude_workspaces: "special:.*",
|
||||
),
|
||||
switch: (
|
||||
modifier: "alt",
|
||||
@@ -82,7 +83,8 @@
|
||||
current_monitor,
|
||||
],
|
||||
switch_workspaces: false,
|
||||
exclude_special_workspaces: "",
|
||||
exclude_workspaces: "",
|
||||
kill_key: 'q',
|
||||
),
|
||||
switch_2: None,
|
||||
),
|
||||
|
||||
@@ -0,0 +1,279 @@
|
||||
{
|
||||
"name": "desk",
|
||||
"monitors": [
|
||||
{
|
||||
"name": "eDP-2",
|
||||
"description": "BOE 0x0BC9",
|
||||
"make": "BOE",
|
||||
"model": "0x0BC9",
|
||||
"serial": "",
|
||||
"width": 2560,
|
||||
"height": 1600,
|
||||
"refresh_rate": 165.0,
|
||||
"resolution_mode": "explicit",
|
||||
"available_modes": [
|
||||
"2560x1600@165.00Hz",
|
||||
"2560x1600@60.00Hz",
|
||||
"1920x1200@165.00Hz",
|
||||
"1920x1080@165.00Hz",
|
||||
"1600x1200@165.00Hz",
|
||||
"1680x1050@165.00Hz",
|
||||
"1280x1024@165.00Hz",
|
||||
"1440x900@165.00Hz",
|
||||
"1280x800@165.00Hz",
|
||||
"1280x720@165.00Hz",
|
||||
"1024x768@165.00Hz",
|
||||
"800x600@165.00Hz",
|
||||
"640x480@165.00Hz"
|
||||
],
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"position_mode": "explicit",
|
||||
"scale": 1,
|
||||
"scale_mode": "explicit",
|
||||
"transform": 0,
|
||||
"mirror_of": "",
|
||||
"bitdepth": 8,
|
||||
"vrr": 0,
|
||||
"color_management": "srgb",
|
||||
"icc_profile": "",
|
||||
"sdr_brightness": 1,
|
||||
"sdr_saturation": 1,
|
||||
"sdr_eotf": 0,
|
||||
"supports_hdr": 0,
|
||||
"supports_wide_color": 0,
|
||||
"sdr_min_luminance": 0.2,
|
||||
"sdr_max_luminance": 80,
|
||||
"min_luminance": 0.0,
|
||||
"max_luminance": 0.0,
|
||||
"max_avg_luminance": 0.0,
|
||||
"reserved_top": 0,
|
||||
"reserved_bottom": 0,
|
||||
"reserved_left": 0,
|
||||
"reserved_right": 0,
|
||||
"enabled": true,
|
||||
"focus_at_startup": false
|
||||
},
|
||||
{
|
||||
"name": "DP-7",
|
||||
"description": "Dell Inc. DELL U2515HX GMDK46C4053L",
|
||||
"make": "Dell Inc.",
|
||||
"model": "DELL U2515HX",
|
||||
"serial": "GMDK46C4053L",
|
||||
"width": 2560,
|
||||
"height": 1440,
|
||||
"refresh_rate": 59.951,
|
||||
"resolution_mode": "explicit",
|
||||
"available_modes": [
|
||||
"2560x1440@59.95Hz",
|
||||
"2048x1152@60.00Hz",
|
||||
"1920x1200@59.88Hz",
|
||||
"1920x1080@60.00Hz",
|
||||
"1920x1080@60.00Hz",
|
||||
"1920x1080@59.94Hz",
|
||||
"1920x1080@50.00Hz",
|
||||
"1920x1080@30.00Hz",
|
||||
"1920x1080@29.97Hz",
|
||||
"1920x1080@25.00Hz",
|
||||
"1920x1080@24.00Hz",
|
||||
"1920x1080@23.98Hz",
|
||||
"1600x1200@60.00Hz",
|
||||
"1680x1050@59.95Hz",
|
||||
"1280x1024@75.03Hz",
|
||||
"1280x1024@60.02Hz",
|
||||
"1200x960@59.99Hz",
|
||||
"1152x864@75.00Hz",
|
||||
"1280x720@60.00Hz",
|
||||
"1280x720@60.00Hz",
|
||||
"1280x720@59.94Hz",
|
||||
"1280x720@50.00Hz",
|
||||
"1024x768@75.03Hz",
|
||||
"1024x768@60.00Hz",
|
||||
"800x600@75.00Hz",
|
||||
"800x600@60.32Hz",
|
||||
"720x576@50.00Hz",
|
||||
"720x480@60.00Hz",
|
||||
"720x480@60.00Hz",
|
||||
"720x480@59.94Hz",
|
||||
"720x480@59.94Hz",
|
||||
"720x480@59.94Hz",
|
||||
"640x480@75.00Hz",
|
||||
"640x480@60.00Hz",
|
||||
"640x480@59.94Hz",
|
||||
"640x480@59.94Hz",
|
||||
"720x400@70.08Hz"
|
||||
],
|
||||
"x": 5488,
|
||||
"y": 345,
|
||||
"position_mode": "explicit",
|
||||
"scale": 1,
|
||||
"scale_mode": "explicit",
|
||||
"transform": 0,
|
||||
"mirror_of": "",
|
||||
"bitdepth": 8,
|
||||
"vrr": 0,
|
||||
"color_management": "srgb",
|
||||
"icc_profile": "",
|
||||
"sdr_brightness": 1,
|
||||
"sdr_saturation": 1,
|
||||
"sdr_eotf": 0,
|
||||
"supports_hdr": 0,
|
||||
"supports_wide_color": 0,
|
||||
"sdr_min_luminance": 0.2,
|
||||
"sdr_max_luminance": 80,
|
||||
"min_luminance": 0.0,
|
||||
"max_luminance": 0.0,
|
||||
"max_avg_luminance": 0.0,
|
||||
"reserved_top": 0,
|
||||
"reserved_bottom": 0,
|
||||
"reserved_left": 0,
|
||||
"reserved_right": 0,
|
||||
"enabled": true,
|
||||
"focus_at_startup": false
|
||||
},
|
||||
{
|
||||
"name": "DP-10",
|
||||
"description": "Dell Inc. DELL U2518D 0WG2J9C5B3WL",
|
||||
"make": "Dell Inc.",
|
||||
"model": "DELL U2518D",
|
||||
"serial": "0WG2J9C5B3WL",
|
||||
"width": 2560,
|
||||
"height": 1440,
|
||||
"refresh_rate": 59.951,
|
||||
"resolution_mode": "explicit",
|
||||
"available_modes": [
|
||||
"2560x1440@59.95Hz",
|
||||
"2048x1080@60.00Hz",
|
||||
"2048x1080@24.00Hz",
|
||||
"1920x1080@60.00Hz",
|
||||
"1920x1080@60.00Hz",
|
||||
"1920x1080@59.94Hz",
|
||||
"1920x1080@50.00Hz",
|
||||
"1600x1200@60.00Hz",
|
||||
"1280x1024@75.03Hz",
|
||||
"1280x1024@60.02Hz",
|
||||
"1152x864@75.00Hz",
|
||||
"1280x720@60.00Hz",
|
||||
"1280x720@60.00Hz",
|
||||
"1280x720@59.94Hz",
|
||||
"1280x720@50.00Hz",
|
||||
"1024x768@75.03Hz",
|
||||
"1024x768@60.00Hz",
|
||||
"800x600@75.00Hz",
|
||||
"800x600@60.32Hz",
|
||||
"720x576@50.00Hz",
|
||||
"720x576@50.00Hz",
|
||||
"720x480@60.00Hz",
|
||||
"720x480@60.00Hz",
|
||||
"720x480@59.94Hz",
|
||||
"720x480@59.94Hz",
|
||||
"640x480@75.00Hz",
|
||||
"640x480@60.00Hz",
|
||||
"640x480@59.94Hz",
|
||||
"640x480@59.94Hz",
|
||||
"720x400@70.08Hz"
|
||||
],
|
||||
"x": 2928,
|
||||
"y": 345,
|
||||
"position_mode": "explicit",
|
||||
"scale": 1,
|
||||
"scale_mode": "explicit",
|
||||
"transform": 0,
|
||||
"mirror_of": "",
|
||||
"bitdepth": 8,
|
||||
"vrr": 0,
|
||||
"color_management": "srgb",
|
||||
"icc_profile": "",
|
||||
"sdr_brightness": 1,
|
||||
"sdr_saturation": 1,
|
||||
"sdr_eotf": 0,
|
||||
"supports_hdr": 0,
|
||||
"supports_wide_color": 0,
|
||||
"sdr_min_luminance": 0.2,
|
||||
"sdr_max_luminance": 80,
|
||||
"min_luminance": 0.0,
|
||||
"max_luminance": 0.0,
|
||||
"max_avg_luminance": 0.0,
|
||||
"reserved_top": 0,
|
||||
"reserved_bottom": 0,
|
||||
"reserved_left": 0,
|
||||
"reserved_right": 0,
|
||||
"enabled": true,
|
||||
"focus_at_startup": false
|
||||
},
|
||||
{
|
||||
"name": "DP-4",
|
||||
"description": "Viewteck Co. Ltd. GNV34DB",
|
||||
"make": "Viewteck Co., Ltd.",
|
||||
"model": "GNV34DB",
|
||||
"serial": "",
|
||||
"width": 3440,
|
||||
"height": 1440,
|
||||
"refresh_rate": 50.0,
|
||||
"resolution_mode": "explicit",
|
||||
"available_modes": [
|
||||
"3440x1440@30.00Hz",
|
||||
"3440x1440@50.00Hz",
|
||||
"3440x1440@50.00Hz",
|
||||
"2560x1080@60.00Hz",
|
||||
"2560x1080@59.94Hz",
|
||||
"1720x1440@60.00Hz",
|
||||
"1920x1080@60.00Hz",
|
||||
"1920x1080@60.00Hz",
|
||||
"1920x1080@59.94Hz",
|
||||
"1920x1080@50.00Hz",
|
||||
"1680x1050@59.88Hz",
|
||||
"1600x900@60.00Hz",
|
||||
"1280x1024@75.03Hz",
|
||||
"1280x1024@60.02Hz",
|
||||
"1440x900@59.90Hz",
|
||||
"1280x720@60.00Hz",
|
||||
"1280x720@60.00Hz",
|
||||
"1280x720@59.94Hz",
|
||||
"1280x720@50.00Hz",
|
||||
"1024x768@75.03Hz",
|
||||
"1024x768@60.00Hz",
|
||||
"800x600@75.00Hz",
|
||||
"800x600@60.32Hz",
|
||||
"720x480@60.00Hz",
|
||||
"720x480@60.00Hz",
|
||||
"720x480@59.94Hz",
|
||||
"720x480@59.94Hz",
|
||||
"640x480@75.00Hz",
|
||||
"640x480@60.00Hz",
|
||||
"640x480@59.94Hz",
|
||||
"640x480@59.94Hz",
|
||||
"720x400@70.08Hz"
|
||||
],
|
||||
"x": 3795,
|
||||
"y": 1785,
|
||||
"position_mode": "explicit",
|
||||
"scale": 1,
|
||||
"scale_mode": "explicit",
|
||||
"transform": 0,
|
||||
"mirror_of": "",
|
||||
"bitdepth": 8,
|
||||
"vrr": 0,
|
||||
"color_management": "srgb",
|
||||
"icc_profile": "",
|
||||
"sdr_brightness": 1,
|
||||
"sdr_saturation": 1,
|
||||
"sdr_eotf": 0,
|
||||
"supports_hdr": 0,
|
||||
"supports_wide_color": 0,
|
||||
"sdr_min_luminance": 0.2,
|
||||
"sdr_max_luminance": 80,
|
||||
"min_luminance": 0.0,
|
||||
"max_luminance": 0.0,
|
||||
"max_avg_luminance": 0.0,
|
||||
"reserved_top": 0,
|
||||
"reserved_bottom": 0,
|
||||
"reserved_left": 0,
|
||||
"reserved_right": 0,
|
||||
"enabled": true,
|
||||
"focus_at_startup": false
|
||||
}
|
||||
],
|
||||
"workspace_rules": [],
|
||||
"last_applied_time": 1788832961.6364207
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"name": "laptop",
|
||||
"monitors": [
|
||||
{
|
||||
"name": "eDP-2",
|
||||
"description": "BOE 0x0BC9",
|
||||
"make": "BOE",
|
||||
"model": "0x0BC9",
|
||||
"serial": "",
|
||||
"width": 2560,
|
||||
"height": 1600,
|
||||
"refresh_rate": 165.0,
|
||||
"resolution_mode": "explicit",
|
||||
"available_modes": [
|
||||
"2560x1600@165.00Hz",
|
||||
"2560x1600@60.00Hz",
|
||||
"1920x1200@165.00Hz",
|
||||
"1920x1080@165.00Hz",
|
||||
"1600x1200@165.00Hz",
|
||||
"1680x1050@165.00Hz",
|
||||
"1280x1024@165.00Hz",
|
||||
"1440x900@165.00Hz",
|
||||
"1280x800@165.00Hz",
|
||||
"1280x720@165.00Hz",
|
||||
"1024x768@165.00Hz",
|
||||
"800x600@165.00Hz",
|
||||
"640x480@165.00Hz"
|
||||
],
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"position_mode": "explicit",
|
||||
"scale": 1,
|
||||
"scale_mode": "explicit",
|
||||
"transform": 0,
|
||||
"mirror_of": "",
|
||||
"bitdepth": 8,
|
||||
"vrr": 0,
|
||||
"color_management": "srgb",
|
||||
"icc_profile": "",
|
||||
"sdr_brightness": 1,
|
||||
"sdr_saturation": 1,
|
||||
"sdr_eotf": 0,
|
||||
"supports_hdr": 0,
|
||||
"supports_wide_color": 0,
|
||||
"sdr_min_luminance": 0.2,
|
||||
"sdr_max_luminance": 80,
|
||||
"min_luminance": 0.0,
|
||||
"max_luminance": 0.0,
|
||||
"max_avg_luminance": 0.0,
|
||||
"reserved_top": 0,
|
||||
"reserved_bottom": 0,
|
||||
"reserved_left": 0,
|
||||
"reserved_right": 0,
|
||||
"enabled": true,
|
||||
"focus_at_startup": false
|
||||
}
|
||||
],
|
||||
"workspace_rules": [],
|
||||
"last_applied_time": 1788832965.6726744
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"clamshell_mode": true,
|
||||
"update_sddm": true,
|
||||
"migrate_workspaces": true
|
||||
"migrate_workspaces": true,
|
||||
"active_profile": "laptop"
|
||||
}
|
||||
|
||||
+1
-1
Submodule nvim/.config/nvim updated: 94b2c40db1...b548abcf80
@@ -19,8 +19,8 @@ StartLimitBurst=5
|
||||
[Service]
|
||||
PassEnvironment=DISPLAY WAYLAND_DISPLAY DBUS_SESSION_BUS_ADDRESS XDG_RUNTIME_DIR
|
||||
Environment="OP_BIOMETRIC_UNLOCK_ENABLED=true"
|
||||
Environment="CF_ACCESS_CLIENT_ID=op://Homelab/K8s API Service Token/Service Token/client-id"
|
||||
Environment="CF_ACCESS_CLIENT_SECRET=op://Homelab/K8s API Service Token/Service Token/client-secret"
|
||||
Environment="TUNNEL_SERVICE_TOKEN_ID=op://Homelab/K8s API Service Token/Service Token/client-id"
|
||||
Environment="TUNNEL_SERVICE_TOKEN_SECRET=op://Homelab/K8s API Service Token/Service Token/client-secret"
|
||||
ExecStart=/usr/bin/op run -- /usr/bin/cloudflared access tcp --hostname k8s.samoneal.io --url localhost:6443
|
||||
Restart=on-failure
|
||||
RestartSec=60
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"position": "top",
|
||||
"modules-left": ["hyprland/workspaces", "mpris"],
|
||||
"modules-center": ["hyprland/window"],
|
||||
"modules-right": ["cpu", "memory", "tray", "bluetooth", "network", "pulseaudio", "battery", "clock", "power-profiles-daemon", "custom/power"],
|
||||
"modules-right": ["cpu", "memory", "tray", "bluetooth", "network", "pulseaudio", "battery", "custom/weather", "clock", "power-profiles-daemon", "custom/power"],
|
||||
"clock": {
|
||||
"format": "<span foreground='#f5c2e7'> </span>{:%a %d %H:%M}",
|
||||
"tooltip-format": "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>"
|
||||
@@ -28,6 +28,12 @@
|
||||
"memory": {
|
||||
"on-click": "~/.local/bin/btop.sh"
|
||||
},
|
||||
"custom/weather": {
|
||||
"format": "{}",
|
||||
"exec": "~/.local/bin/weather.sh",
|
||||
"interval": 600,
|
||||
"tooltip": false
|
||||
},
|
||||
"tray": {
|
||||
"icon-size": 16,
|
||||
"icon-theme": "Papirus-Dark",
|
||||
@@ -83,10 +89,11 @@
|
||||
"menu": "on-click",
|
||||
"menu-file": "~/.config/waybar/power_menu.xml",
|
||||
"menu-actions": {
|
||||
"shutdown": "shutdown",
|
||||
"reboot": "reboot",
|
||||
"suspend": "systemctl suspend",
|
||||
"hibernate": "systemctl hibernate",
|
||||
"lock": "hyprlock",
|
||||
"logout": "hyprctl dispatch exit",
|
||||
"reboot": "reboot",
|
||||
"shutdown": "shutdown",
|
||||
},
|
||||
"escape": true
|
||||
},
|
||||
|
||||
@@ -7,21 +7,26 @@
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="hibernate">
|
||||
<property name="label">Hibernate</property>
|
||||
<object class="GtkMenuItem" id="lock">
|
||||
<property name="label">Lock</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="shutdown">
|
||||
<property name="label">Shutdown</property>
|
||||
<object class="GtkMenuItem" id="logout">
|
||||
<property name="label">Logout</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="reboot">
|
||||
<property name="label">Restart</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorMenuItem" id="delimiter1" />
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="reboot">
|
||||
<property name="label">Reboot</property>
|
||||
<object class="GtkMenuItem" id="shutdown">
|
||||
<property name="label">Shutdown</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
||||
+59
@@ -139,3 +139,62 @@ alias pip=pip3
|
||||
. "/home/sammieo/.deno/env"
|
||||
|
||||
export LC_ALL="en_US.UTF-8"
|
||||
|
||||
# Make sure no alias hides the real mv / cp
|
||||
unalias mv 2>/dev/null
|
||||
unalias cp 2>/dev/null
|
||||
|
||||
# Custom 'move' command that incorporates the pv command
|
||||
mv() {
|
||||
if (( $# > 2 )); then
|
||||
command mv "$@"
|
||||
return
|
||||
fi
|
||||
|
||||
local src=$1 dest=$2
|
||||
|
||||
if [ -d "$src" ]; then
|
||||
mkdir -p "$dest"
|
||||
|
||||
# Total size in bytes (du -sb)
|
||||
local total=$(du -sb "$src" | awk '{print $1}')
|
||||
|
||||
# Pipe through pv and extract at destination
|
||||
tar -cf - -C "$(dirname "$src")" "$(basename "$src")" |
|
||||
pv -s "$total" |
|
||||
tar -xf - -C "$dest"
|
||||
|
||||
# Remove the original directory
|
||||
rm -rf "$src"
|
||||
else
|
||||
mkdir -p "$(dirname "$dest")"
|
||||
command mv "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
# Custom 'cp' command that incorporates the pv command
|
||||
cp() {
|
||||
if (( $# > 2 )); then
|
||||
command cp "$@"
|
||||
return
|
||||
fi
|
||||
|
||||
local src=$1 dst=$2
|
||||
|
||||
if [ -d "$src" ]; then
|
||||
mkdir -p "$dst"
|
||||
|
||||
# ---- 1️⃣ Total size of the directory ---------------------------------
|
||||
local total=$(du -sb "$src" | awk '{print $1}')
|
||||
|
||||
# ---- 2️⃣ Stream the dir through pv into the destination ---------------
|
||||
tar -cf - -C "$(dirname "$src")" "$(basename "$src")" |
|
||||
pv -s "$total" |
|
||||
tar -xf - -C "$dst"
|
||||
else
|
||||
# ---- 3️⃣ Single file -------------------------------------------------
|
||||
mkdir -p "$(dirname "$dst")"
|
||||
local fsize=$(stat -c%s "$src" 2>/dev/null || wc -c <"$src")
|
||||
pv -s "$fsize" < "$src" > "$dst"
|
||||
fi
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user