1 Commits

Author SHA1 Message Date
kenji 962925e35b feat(hyprland): integrate force-switch script with split:workspace 2026-01-05 12:46:42 -06:00
94 changed files with 695 additions and 3046 deletions
+32 -73
View File
@@ -5,15 +5,9 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Build Commands
```bash
# Rebuild and switch to new configuration (desktop x86_64)
# Rebuild and switch to new configuration
sudo nixos-rebuild switch --flake ~/.config/nixos/#hakase
# Rebuild MacBook configuration (aarch64)
sudo nixos-rebuild switch --flake ~/.config/nixos/#macbook
# Dry-run build to check for errors without applying
sudo nixos-rebuild build --flake ~/.config/nixos/#hakase
# Manage SOPS secrets
nix-shell -p sops --run "sops secrets/secrets.yaml"
nix-shell -p sops --run "sops updatekeys secrets/secrets.yaml"
@@ -21,100 +15,65 @@ nix-shell -p sops --run "sops updatekeys secrets/secrets.yaml"
## Architecture Overview
This is a modular, flake-based NixOS configuration supporting two hosts: `hakase` (x86_64 desktop) and `macbook` (aarch64 Apple Silicon).
This is a modular, flake-based NixOS configuration for a single host (`hakase`).
### Key Entry Points
- `flake.nix` - Declares inputs and creates both NixOS configurations (hakase, macbook)
- `config.nix` - Central configuration values separated by host (hakase, macbook keys)
- `hosts/{hakase,macbook}/configuration.nix` - Host-level entry points importing system modules
- `home/hakase.nix` - Home Manager entry point for user environment (referenced from flake)
- `flake.nix` - Declares inputs and creates NixOS configuration
- `config.nix` - Central configuration values (username, hostname, paths, theme settings, bookmarks)
- `hosts/hakase/configuration.nix` - Host-level entry point that imports system modules
### Module Organization
**Three-tier system:**
1. **System modules** (`modules/nixos/`) - NixOS-level settings (boot, kernel, services, hardware)
2. **Home Manager modules** (`modules/home/`) - User-level environment and applications
3. **Application configs** (`apps/`) - Per-application configuration directories with `default.nix` files
**Two-tier module system:**
- `modules/nixos/` - NixOS system-level modules (boot, kernel, services, hardware)
- `modules/home/` - Home Manager user-level modules (imported via `home/hakase.nix`)
Examples:
- `apps/hyprland/default.nix` + `apps/hyprland/hypr/*.nix` - Hyprland compositor config
- `apps/firefox/default.nix` - Browser with bookmarks and theming
- `apps/ghostty/default.nix` - Terminal emulator
- `apps/neovim/default.nix` - Editor (via nixovim external flake)
**Application configs:** Each application has its own directory in `apps/` with a `default.nix` and optional sub-modules (e.g., `apps/hyprland/hypr/*.nix` for Hyprland settings).
### Configuration Flow
```
flake.nix (outputs)
hakase (x86_64-linux)
├─ hosts/hakase/configuration.nix
│ └─ modules/nixos/default.nix (imports system modules)
└─ home-manager
└─ home/hakase.nix
└─ modules/home/* (imports Home Manager modules)
│ └─ apps/* (application configurations)
└─ macbook (aarch64-linux)
├─ hosts/macbook/configuration.nix
│ └─ modules/nixos/default.nix
└─ Similar home-manager structure
config.nix provides myConfig via specialArgs to both configurations
flake.nix
nixosConfigurations.hakase
├─ hosts/hakase/configuration.nix
│ └─ modules/nixos/default.nix (imports all system modules)
└─ home-manager
└─ home/hakase.nix
└─ modules/home/* → apps/*
```
### Configuration Structure (config.nix)
The `config.nix` file defines host-specific configuration under `hakase` and `macbook` keys. Common values include:
```nix
myConfig = {
nixos = { username, hostname, timezone }
git = { username, email, defaultBranch }
theme = { mode } # "dark" or "light"
terminal = { default, font, aliases }
font = { monospace, monospaceScript, sans }
hyprland = { monitors, wallpaper, kb_options }
firefox = { bookmarks, newtabpage }
# ... more app-specific configs
}
```
To add a host-specific override, define it in the host's `myConfig` section in `config.nix`. The flake passes `allConfig.{hostname}` as specialArgs, so modules access the correct host configuration.
### Module Pattern
Modules receive standard NixOS parameters plus custom ones:
Modules receive these parameters:
```nix
{ pkgs, config, lib, myConfig, inputs, system, ... }:
{ pkgs, config, myConfig, inputs, ... }:
```
**Key patterns:**
- Access host config: `myConfig.nixos.username`, `myConfig.terminal.default`
- Use host-specific packages: `pkgs.unstable` (from nixpkgs), `inputs.neovim` (from flake inputs)
- Reference other modules via `config` (e.g., `config.home.homeDirectory`)
- Conditional logic: Check `system` or `myConfig` values
Access configuration values via `myConfig`:
```nix
myConfig.nixos.username # "hakase"
myConfig.nixos.hostname # "hakase"
myConfig.terminal.default # Terminal emulator
myConfig.hyprland.monitors # Monitor configuration
```
### Secrets Management
SOPS-encrypted secrets stored in `secrets/secrets.yaml`. Age key at `~/.config/sops/age/keys.txt`.
Uses SOPS for encrypted secrets. Keys stored at `~/.config/sops/age/keys.txt`.
In modules, reference secrets via:
Access secrets in modules:
```nix
config.sops.secrets.secret_name.path
```
## Key Technologies
- **Hyprland** with UWSM (systemd user session management)
- **Matugen** for automatic system-wide theming from wallpaper colors
- **Home Manager** for user environment and program configuration
- **nixovim** external flake for Neovim configuration (treesitter disabled due to read-only NixOS constraints)
- **SOPS-Nix** for secrets encryption
- **CachyOS kernel** on hakase (x86_64), **Asahi Linux** on macbook (aarch64)
- **Hyprland** with UWSM (systemd session management)
- **Stylix** for system-wide theming from wallpaper colors
- **Home Manager** for user environment
- **nixovim** flake for Neovim configuration
## Git Commit Convention
Use conventional commits with scope: `feat(scope):`, `fix(scope):`, `refactor:`, `add:`, `remove:`, `cleanup:`
Common scopes: `nixos`, `home`, `apps`, `config`, `modules`, `hyprland`, `firefox`, etc.
Use conventional commits: `feat(scope):`, `fix(scope):`, `refactor:`, `add:`, `remove:`, `cleanup:`
+18 -17
View File
@@ -1,16 +1,16 @@
# HakaseOS
A modular, flake-based NixOS configuration for my personal devices (`hakase` desktop and `macbook`). Heavily inspired by [OmarchyOS](https://omarchy.org/).
A modular, flake-based NixOS configuration for a single host (`hakase`). Heavily inspired by [OmarchyOS](https://omarchy.org/).
## Features
- **Hyprland** compositor with UWSM (systemd session management)
- **Multi-Architecture Support**: Runs on x86_64 (Desktop) and aarch64 (Apple Silicon M1/M2)
- **Matugen** for automatic system-wide theming from wallpaper colors
- **Multi-monitor support** for intuitive desktop management
- **Hardened Firefox** with custom bookmarks and new tab page
- **Vim keybindings** throughout the system
- **SOPS** for encrypted secrets management
- **CachyOS kernel** (Desktop) and **Asahi Linux** (MacBook) support
- **CachyOS kernel** via chaotic-nyx for performance optimizations
## 🚧 TODO
- LUKS designed
@@ -24,19 +24,19 @@ A modular, flake-based NixOS configuration for my personal devices (`hakase` des
![Desktop Music](assets/example/desktop_music.png)
![Desktop with Hakase](assets/example/desktop_hakase.png)
## Structure
```
.
├── flake.nix # Entry point defining hosts (hakase, macbook)
├── config.nix # Central configuration values per host
├── flake.nix # Flake inputs and NixOS configuration
├── config.nix # Central configuration values
├── hosts/
── hakase/ # Desktop configuration (x86_64)
│ └── macbook/ # Laptop configuration (aarch64, Apple Silicon)
── hakase/ # Host-specific configuration
├── modules/
│ ├── nixos/ # System-level modules (boot, kernel, services)
│ └── home/ # Home Manager modules
├── home/ # Host-specific Home Manager entry points
├── apps/ # Per-application configurations
│ ├── hyprland/ # Hyprland window manager
│ ├── waybar/ # Status bar
@@ -53,14 +53,14 @@ A modular, flake-based NixOS configuration for my personal devices (`hakase` des
### Rebuild System
**Desktop (Hakase):**
```bash
sudo nixos-rebuild switch --flake ~/.config/nixos/#hakase
```
**MacBook (Asahi):**
Or use the configured alias:
```bash
sudo nixos-rebuild switch --flake ~/.config/nixos/#macbook
update
```
### Manage Secrets
@@ -75,11 +75,13 @@ nix-shell -p sops --run "sops updatekeys secrets/secrets.yaml"
## Configuration
Central configuration values are defined in `config.nix`, separated by host:
Central configuration values are defined in `config.nix`:
- `hakase` / `macbook` keys define host-specific overrides
- `myConfig.nixos` - System settings (username, hostname, timezone)
- `myConfig.hyprland` - Monitor configuration (Hz, Resolution) and wallpaper
- `myConfig.git` - Git configuration
- `myConfig.terminal` - Default terminal and aliases
- `myConfig.hyprland` - Monitor configuration and wallpaper
- `myConfig.firefox` - Bookmarks and new tab settings
## Flake Inputs
@@ -88,8 +90,7 @@ Central configuration values are defined in `config.nix`, separated by host:
| nixpkgs | NixOS unstable |
| home-manager | User environment management |
| hyprland | Wayland compositor |
| chaotic | CachyOS kernel and packages (x86 only) |
| apple-silicon | Asahi Linux support for NixOS (aarch64 only) |
| chaotic | CachyOS kernel and packages |
| sops-nix | Secrets management |
| nixovim | Neovim configuration |
| matugen | System-wide theming |
@@ -98,4 +99,4 @@ Central configuration values are defined in `config.nix`, separated by host:
## License
Personal configuration - use at your own discretion.
Personal configuration - use at your own discretion.
-12
View File
@@ -1,12 +0,0 @@
{pkgs, ...}: {
home.packages = with pkgs; [anki-bin];
xdg.mimeApps = {
enable = true;
defaultApplications = {
"application/x-apkg" = "anki.desktop";
"application/x-anki-deck" = "anki.desktop";
"application/x-anki-collection" = "anki.desktop";
};
};
}
-39
View File
@@ -1,39 +0,0 @@
{pkgs, ...}: {
programs.bottom = {
enable = true;
settings = {
flags = {
rate = 1000;
hide_table_gap = true;
hide_time = true;
left_legend = true;
network_use_bytes = true;
temperature_type = "c";
mem_as_value = true;
current_usage = true;
};
row = [
{
ratio = 4;
child = [
{ type = "cpu"; }
];
}
{
ratio = 3;
child = [
{ type = "mem"; }
{ type = "net"; }
];
}
{
ratio = 3;
child = [
{ type = "temp"; }
{ type = "disk"; }
];
}
];
};
};
}
+1 -26
View File
@@ -1,35 +1,10 @@
{
pkgs,
lib,
myConfig,
...
}: {
# This enables the btop configuration file generation in your home directory.
# The btop package itself is now installed system-wide via modules/nixos/btop.nix
programs.btop = {
enable = true;
settings = {
vim_keys = true;
color_theme = "TTY";
theme_background = false;
presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:default cpu:0:block,net:0:tty cpu:0:default,mem:0:default,net:0:default,gpu0:0:default";
};
};
# This updates your Hyprland settings to use the btop-power wrapper.
wayland.windowManager.hyprland.settings = lib.mkMerge [
{
bindd = [
"CTRL SHIFT, Escape, Open Btop Minimal, exec, uwsm app -- xdg-terminal-exec -e btop-power -p 2"
];
}
(lib.mkIf (myConfig.btop.autostart) {
exec-once = [
"uwsm app -- xdg-terminal-exec -e btop-power -p 2"
];
windowrule = [
"match:title ^(btop)$, monitor ${myConfig.btop.monitor}"
];
})
];
}
}
+4 -43
View File
@@ -13,19 +13,14 @@
"SUPER, W, Open Browser, exec, uwsm app -- firefox"
"SUPER, Y, Toggle YouTube, togglespecialworkspace, youtube"
"SUPER SHIFT, Y, Move to YouTube Special Workspace, movetoworkspace, special:youtube"
"SUPER, I, Toggle Jellyfin, togglespecialworkspace, jellyfin"
"SUPER SHIFT, I, Move to Jellyfin Special Workspace, movetoworkspace, special:jellyfin"
];
workspace = [
"special:youtube, on-created-empty:uwsm app -- firefox -P web-app --name youtube https://youtube.com"
"special:jellyfin, on-created-empty:uwsm app -- firefox -P web-app --name jellyfin https://watch.sakamoto.dev"
"special:youtube, on-created-empty:uwsm app -- firefox -P YouTube --name youtube"
];
windowrule = [
"match:class (?i)(firefox|youtube|jellyfin), opacity 1 1"
"match:class ^(youtube)$, workspace special:youtube"
"match:class ^(jellyfin)$, workspace special:jellyfin"
windowrulev2 = [
"workspace special:youtube, class:^(youtube)$"
];
};
imports = [
@@ -43,22 +38,8 @@
bind J tabnext
bind K tabprev
unbind <C-e>
" Force Tridactyl to yield new tab control to Firefox/Extensions
set newtab about:newtab
'';
xdg.mimeApps = {
enable = true;
defaultApplications = {
"text/html" = "firefox.desktop";
"x-scheme-handler/http" = "firefox.desktop";
"x-scheme-handler/https" = "firefox.desktop";
"x-scheme-handler/about" = "firefox.desktop";
"x-scheme-handler/unknown" = "firefox.desktop";
};
};
programs.firefox = {
enable = true;
languagePacks = ["en-US"];
@@ -68,34 +49,14 @@
];
profiles = {
youtube = import ./profiles/web-app.nix {
inherit pkgs myConfig;
id = 1;
name = "YouTube";
url = "https://youtube.com";
};
jellyfin = import ./profiles/web-app.nix {
inherit pkgs myConfig;
id = 2;
name = "Jellyfin";
url = "https://watch.sakamoto.dev";
};
web-app = import ./profiles/web-app.nix {
inherit pkgs myConfig;
id = 3;
name = "web-app";
url = "about:blank";
};
youtube = import ./profiles/youtube.nix {inherit pkgs myConfig;};
hakase = {
search.force = true;
isDefault = true;
search.default = "ddg";
extensions.packages = with pkgs.nur.repos.rycee.firefox-addons; [
pywalfox
ublock-origin
bitwarden
tridactyl
new-tab-override
];
bookmarks = {
-178
View File
@@ -1,178 +0,0 @@
{
pkgs,
myConfig,
id,
name,
url,
...
}: {
inherit id name;
# Note: This profile relies on the global tridactylrc logic in default.nix
# to dynamically set 'newtab' via the TRIDACTYL_NEWTAB environment variable.
search.force = true;
search.default = "ddg";
extensions.force = true;
extensions.packages = with pkgs.nur.repos.rycee.firefox-addons; [
ublock-origin
bitwarden
tridactyl
new-tab-override
pywalfox
];
settings = {
# --- New Tab Override ---
"extensions.newtaboverride@agenedia.com.url" = url;
"extensions.newtaboverride@agenedia.com.type" = 1; # URL mode
# --- Privacy & Hardening ---
"browser.contentblocking.category" = "strict";
"privacy.trackingprotection.enabled" = true;
"privacy.resistFingerprinting" = true; # Note: Spoofs timezone and caps FPS to 60
"geo.enabled" = false;
"media.peerconnection.enabled" = false; # Prevents WebRTC IP leaks
"network.dns.disablePrefetch" = true;
"network.prefetch-next" = false;
# --- NixOS / Hyprland Integration ---
"widget.use-xdg-desktop-portal.file-picker" = 1; # Use native file picker
# --- UI & Behavior ---
"browser.toolbars.bookmarks.visibility" = "never";
"browser.compactmode.show" = true;
"browser.tabs.closeWindowWithLastTab" = false;
"extensions.pocket.enabled" = false;
"extensions.screenshots.disabled" = true;
"browser.topsites.contile.enabled" = false;
"browser.formfill.enable" = false;
"browser.search.suggest.enabled" = false;
"browser.search.suggest.enabled.private" = false;
"browser.urlbar.suggest.searches" = false;
"browser.urlbar.showSearchSuggestionsFirst" = false;
"browser.newtabpage.activity-stream.feeds.section.topstories" = false;
"browser.newtabpage.activity-stream.feeds.snippets" = false;
"browser.newtabpage.activity-stream.section.highlights.includePocket" = false;
"browser.newtabpage.activity-stream.section.highlights.includeBookmarks" = false;
"browser.newtabpage.activity-stream.section.highlights.includeDownloads" = false;
"browser.newtabpage.activity-stream.section.highlights.includeVisited" = false;
"browser.newtabpage.activity-stream.showSponsored" = false;
"browser.newtabpage.activity-stream.system.showSponsored" = false;
"browser.newtabpage.activity-stream.showSponsoredTopSites" = false;
"toolkit.legacyUserProfileCustomizations.stylesheets" = true;
"extensions.autoDisableScopes" = 0; # Enable extensions by default
# --- Homepage & Navigation ---
"browser.startup.page" = 1; # Always open the homepage
"browser.startup.homepage" = url;
"browser.newtab.url" = url; # Try to set newtab to homepage
"browser.sessionstore.resume_from_crash" = false; # Always start fresh
"browser.sessionstore.max_tabs_undo" = 0; # Disable undo close tab
# --- DNS over HTTPS (Quad9) ---
"network.trr.mode" = 2; # Use DoH with system fallback
"network.trr.uri" = "https://dns.quad9.net/dns-query";
};
#
# userChrome = ''
# /* --- Autohide Entire Toolbox (Tabs + Address Bar) --- */
# /* Adapted from MrOtherGuy's autohide_main_toolbar.css */
#
# :root{
# /* Height of Tabs + Nav Bar approx 80px */
# --uc-navbar-transform: -85px;
# --uc-autohide-toolbar-delay: 0.1s;
# --uc-autohide-toolbar-duration: 200ms;
# }
# :root[uidensity="compact"]{ --uc-navbar-transform: -70px }
#
# #navigator-toolbox > div{ display: contents; }
#
# /* Apply transform to TabsToolbar AND Nav-bar */
# :root[sessionrestored] :where(#nav-bar,#PersonalToolbar,#TabsToolbar,#tab-notification-deck,.global-notificationbox,#notifications-toolbar){
# transform: translateY(var(--uc-navbar-transform))
# }
#
# :root:is([customizing],[chromehidden*="toolbar"]) :where(#nav-bar,#PersonalToolbar,#TabsToolbar,#tab-notification-deck,.global-notificationbox,#notifications-toolbar){
# transform: none !important;
# opacity: 1 !important;
# }
#
# /* Hide styles for Nav-Bar AND TabsToolbar */
# :where(#nav-bar,#TabsToolbar):not([customizing]){
# opacity: 0;
# transition: transform var(--uc-autohide-toolbar-duration) ease var(--uc-autohide-toolbar-delay), opacity var(--uc-autohide-toolbar-duration) ease var(--uc-autohide-toolbar-delay) !important;
# position: relative;
# z-index: 2;
# background-color: #1c1b22 !important; /* Solid background */
# }
#
# #navigator-toolbox,
# #sidebar-box,
# #sidebar-main,
# #sidebar-splitter,
# #tabbrowser-tabbox{
# z-index: auto !important;
# }
#
# /* Show when toolbox is focused or hovered */
# #navigator-toolbox:focus-within > .browser-toolbar,
# .browser-titlebar:hover ~ :is(#nav-bar,#PersonalToolbar,#TabsToolbar),
# #nav-bar:hover,
# #TabsToolbar:hover,
# #nav-bar:hover + #PersonalToolbar{
# transform: translateY(0);
# opacity: 1;
# transition-duration: var(--uc-autohide-toolbar-duration), var(--uc-autohide-toolbar-duration) !important;
# transition-delay: 0s !important;
# }
#
# /* Ensure popups still work (URL bar) */
# :root[sessionrestored] #urlbar[popover]{
# opacity: 0;
# pointer-events: none;
# transition: transform var(--uc-autohide-toolbar-duration) ease var(--uc-autohide-toolbar-delay), opacity var(--uc-autohide-toolbar-duration) ease var(--uc-autohide-toolbar-delay);
# transform: translateY(var(--uc-navbar-transform));
# }
# #mainPopupSet:has(> [panelopen]:not(#ask-chat-shortcuts,#selection-shortcut-action-panel,#chat-shortcuts-options-panel,#tab-preview-panel)) ~ toolbox #urlbar[popover],
# .browser-titlebar:is(:hover,:focus-within) ~ #nav-bar #urlbar[popover],
# #nav-bar:is(:hover,:focus-within) #urlbar[popover],
# #urlbar-container > #urlbar[popover]:is([focused],[open]){
# opacity: 1;
# pointer-events: auto;
# transition-delay: 0ms;
# transform: translateY(0);
# }
# :where(:root[sessionrestored]) #urlbar-container > #urlbar[popover]:is([focused],[open]){
# transition-duration: 100ms;
# }
#
# /* --- CRITICAL FIX: Trigger Zone --- */
# /* Since we hide EVERYTHING, we need a hitbox at the top of the screen */
# #navigator-toolbox::after {
# content: "";
# position: fixed;
# top: 0;
# left: 0;
# width: 100%;
# height: 20px; /* Generous hit target */
# z-index: 10000;
# pointer-events: auto;
# }
#
# /* When hitbox is hovered, reveal bars */
# #navigator-toolbox:hover :where(#nav-bar,#PersonalToolbar,#TabsToolbar) {
# transform: translateY(0) !important;
# opacity: 1 !important;
# transition-delay: 0s !important;
# }
#
# /* Move up the content view to fill the gap */
# :root[sessionrestored]:not([chromehidden~="toolbar"]) > body > #browser{
# margin-top: var(--uc-navbar-transform);
# }
#
# /* Fix Titlebar and Bookmarks */
# #titlebar { appearance: none !important; }
# #PersonalToolbar { visibility: collapse !important; }
# '';
}
+120
View File
@@ -0,0 +1,120 @@
{
pkgs,
myConfig,
...
}: {
id = 1;
name = "YouTube";
search.force = true;
search.default = "ddg";
extensions.force = true;
extensions.packages = with pkgs.nur.repos.rycee.firefox-addons; [
ublock-origin
bitwarden
tridactyl
];
settings = {
# --- Privacy & Hardening ---
"browser.contentblocking.category" = "strict";
"privacy.trackingprotection.enabled" = true;
"privacy.resistFingerprinting" = true; # Note: Spoofs timezone and caps FPS to 60
"geo.enabled" = false;
"media.peerconnection.enabled" = false; # Prevents WebRTC IP leaks
"network.dns.disablePrefetch" = true;
"network.prefetch-next" = false;
# --- NixOS / Hyprland Integration ---
"widget.use-xdg-desktop-portal.file-picker" = 1; # Use native file picker
# --- UI & Behavior ---
"browser.compactmode.show" = true;
"browser.tabs.closeWindowWithLastTab" = false;
"extensions.pocket.enabled" = false;
"extensions.screenshots.disabled" = true;
"browser.topsites.contile.enabled" = false;
"browser.formfill.enable" = false;
"browser.search.suggest.enabled" = false;
"browser.search.suggest.enabled.private" = false;
"browser.urlbar.suggest.searches" = false;
"browser.urlbar.showSearchSuggestionsFirst" = false;
"browser.newtabpage.activity-stream.feeds.section.topstories" = false;
"browser.newtabpage.activity-stream.feeds.snippets" = false;
"browser.newtabpage.activity-stream.section.highlights.includePocket" = false;
"browser.newtabpage.activity-stream.section.highlights.includeBookmarks" = false;
"browser.newtabpage.activity-stream.section.highlights.includeDownloads" = false;
"browser.newtabpage.activity-stream.section.highlights.includeVisited" = false;
"browser.newtabpage.activity-stream.showSponsored" = false;
"browser.newtabpage.activity-stream.system.showSponsored" = false;
"browser.newtabpage.activity-stream.showSponsoredTopSites" = false;
"toolkit.legacyUserProfileCustomizations.stylesheets" = true;
"extensions.autoDisableScopes" = 0; # Enable extensions by default
# --- Homepage & Navigation ---
"browser.startup.homepage" = "https://youtube.com";
"browser.newtabpage.pinned" = myConfig.firefox.newtabpage;
# --- DNS over HTTPS (Quad9) ---
"network.trr.mode" = 2; # Use DoH with system fallback
"network.trr.uri" = "https://dns.quad9.net/dns-query";
};
userChrome = ''
/* --- Floating Autohide Toolbox (Tabs Only) --- */
/* Take toolbox out of the document flow so web content is 100% height */
#navigator-toolbox {
position: fixed !important;
top: 0;
left: 0;
width: 100%;
z-index: 9999 !important;
background-color: var(--toolbar-bgcolor, #1c1b22) !important;
/* Start hidden */
transform: translateY(-100%) !important;
opacity: 0 !important;
transition: transform 0.2s ease, opacity 0.2s ease !important;
}
/* Trigger zone */
#navigator-toolbox::after {
content: "";
position: absolute;
top: 100%;
left: 0;
width: 100%;
height: 10px;
z-index: 10000 !important;
}
/* Reveal when hovering */
#navigator-toolbox:hover {
transform: translateY(0) !important;
opacity: 1 !important;
}
/* --- Hide specific bars --- */
/* Hide Navigation Bar (Address Bar) COMPLETELY */
#nav-bar {
visibility: collapse !important;
height: 0px !important;
min-height: 0px !important;
padding: 0 !important;
margin: 0 !important;
}
/* Hide Bookmarks Toolbar */
#PersonalToolbar { visibility: collapse !important; }
/* Hide Titlebar */
#titlebar { appearance: none !important; }
/* Ensure TabsToolbar looks okay on its own */
#TabsToolbar {
border: none !important;
background: transparent !important;
}
'';
}
+1 -1
View File
@@ -1,7 +1,7 @@
{
textfox = {
enable = true;
profiles = ["hakase" "web-app"];
profile = "hakase";
config = {
# background = {
# color = "#123456";
-6
View File
@@ -1,7 +1,6 @@
{
config,
pkgs,
myConfig,
...
}: {
home.packages = [
@@ -55,16 +54,11 @@
enableFishIntegration = true;
settings = {
font-family = myConfig.terminal.font;
confirm-close-surface = false;
app-notifications = false;
window-padding-x = 15;
window-padding-y = 15;
window-padding-balance = true;
gtk-titlebar = false;
mouse-hide-while-typing = true;
copy-on-select = "clipboard";
auto-update = "off";
};
};
+4 -4
View File
@@ -10,8 +10,8 @@
general = {
after_sleep_cmd = "hyprctl dispatch dpms on";
ignore_dbus_inhibit = false;
lock_cmd = "hakase-hyprlock";
before_sleep_cmd = "hakase-hyprlock"; # lock before suspend
lock_cmd = "hyprlock";
before_sleep_cmd = "loginctl lock-session"; # lock before suspend
};
listener = [
@@ -21,7 +21,7 @@
# }
{
timeout = 300; # 5min
on-timeout = "hakase-hyprlock"; # lock screen when timeout has passed
on-timeout = "loginctl lock-session"; # lock screen when timeout has passed
}
{
timeout = 330; # 5.5min
@@ -29,7 +29,7 @@
on-resume = "hyprctl dispatch dpms on"; # screen on when activity is detected after timeout has passed
}
{
timeout = 660;
timeout = 1800; # 30min
on-timeout = "systemctl suspend"; # suspend pc
}
];
+3 -5
View File
@@ -14,15 +14,13 @@
./hypr/rules.nix
./scripts/movement.nix
./scripts/window-rules.nix
./scripts/workspace-toggle.nix
];
wayland.windowManager.hyprland.enable = true;
wayland.windowManager.hyprland.systemd.enable = false; # for UWSM support...
wayland.windowManager.hyprland.plugins = [
inputs.hyprsplit.packages.${pkgs.system}.hyprsplit
# inputs.hypr-dynamic-cursors.packages.${pkgs.system}.hypr-dynamic-cursors
# inputs.hyprspace.packages.${pkgs.system}.Hyprspace
pkgs.hyprlandPlugins.hyprsplit
pkgs.hyprlandPlugins.hypr-dynamic-cursors
pkgs.hyprlandPlugins.hyprspace
pkgs.hyprlandPlugins.hyprbars
];
}
+6 -13
View File
@@ -1,9 +1,6 @@
{pkgs, ...}: {
# TODO: implement a way to show binds, preferably use vicinae.
wayland.windowManager.hyprland.settings = {
binds = {
workspace_back_and_forth = true;
};
bindel = [
", XF86MonBrightnessUp, exec, ddcutil setvcp 10 + 10"
", XF86MonBrightnessDown, exec, ddcutil setvcp 10 - 10"
@@ -30,7 +27,6 @@
"SUPER, K, Move focus up, movefocus, u"
"SUPER, H, Move focus left, movefocus, l"
"SUPER, L, Move focus right, movefocus, r"
"SUPER, G, Switch Focus (Float/Tile), exec, hakase-focus-switch"
# move window
"SUPER SHIFT, h, Move window left, movewindow, l"
@@ -48,7 +44,10 @@
# apps
# "SUPER, SPACE, Open App Launcher, exec, nc -U $XDG_RUNTIME_DIR/walker/walker.sock"
"SUPER CTRL, I, Switch Wallpaper, exec, hakase-wallpaper-switch"
# TODO:
# add text clipping from pictures
# add screen recording
# Special workspace
@@ -58,24 +57,18 @@
# [Workspaces] Toggle between most recent workspaces
"SUPER, Tab, Cycle workspaces, workspace, previous"
# [Workspaces] Move to another workspace
"CTRL SHIFT, H, Move to previous workspace, split:workspace, -1"
"CTRL SHIFT, L, Move to next workspace, split:workspace, +1"
"CTRL SHIFT, K, Move to previous workspace, split:workspace, -1"
"CTRL SHIFT, J, Move to next workspace, split:workspace, +1"
# hyprspace - workspace overview
# "SUPER, E, Toggle Workspace Overview, overview:toggle"
"SUPER, E, Toggle Workspace Overview, overview:toggle"
]
++ (
# Generate binds for Super + [1-5] to switch workspaces with special workspace toggle support
# Generate binds for Super + [1-5] to switch workspaces on current monitor
# and Super + Shift + [1-5] to move window to workspace on current monitor
builtins.concatLists (builtins.genList (
i: let
ws = i + 1;
key = toString ws;
in [
"SUPER, ${key}, Switch to workspace ${toString ws}, exec, workspace-toggle ${toString ws}"
"SUPER, ${key}, Switch to workspace ${toString ws}, exec, hakase-workspace-switch-force ${toString ws}"
"SUPER SHIFT, ${key}, Move window to workspace ${toString ws}, split:movetoworkspace, ${toString ws}"
]
)
+2
View File
@@ -4,6 +4,8 @@
];
wayland.windowManager.hyprland.settings = {
env = [
"HYPRCURSOR_THEME,rose-pine-hyprcursor"
"HYPRCURSOR_SIZE,24"
"GUM_CONFIRM_PROMPT_FOREGROUND,6"
"GUM_CONFIRM_SELECTED_FOREGROUND,0"
"GUM_CONFIRM_SELECTED_BACKGROUND,2"
+1 -2
View File
@@ -15,8 +15,7 @@
# essentials
"hyprpm reload -n"
"systemctl --user start hyprpolkitagent"
"systemctl --user start swayosd"
# "hyprsunset -t 4500" # TODO: must be optional
"hyprsunset -t 4500" # TODO: must be optional
];
};
}
+3 -5
View File
@@ -4,13 +4,11 @@
gaps_in = 5;
gaps_out = 15;
layout = "dwindle";
allow_tearing = true;
resize_on_border = true;
};
decoration = {
rounding = 0;
active_opacity = 1;
inactive_opacity = 0.99;
active_opacity = 0.99;
inactive_opacity = 0.70;
shadow = {
enabled = true;
range = 2;
@@ -21,7 +19,6 @@
enabled = true;
size = 8;
passes = 2;
new_optimizations = true;
special = true;
brightness = 0.60;
contrast = 0.75;
@@ -29,6 +26,7 @@
};
monitor = myConfig.hyprland.monitors;
dwindle = {
pseudotile = true;
preserve_split = true;
smart_split = false;
};
+2 -4
View File
@@ -1,14 +1,12 @@
{myConfig, ...}: {
{
wayland.windowManager.hyprland.settings = {
input = {
repeat_rate = 50;
repeat_delay = 300;
numlock_by_default = true;
kb_options = myConfig.hyprland.kb_options;
};
cursor = {
hide_on_key_press = false;
no_warps = false;
no_warps = true;
};
};
}
+6 -1
View File
@@ -1,7 +1,12 @@
{pkgs, ...}: {
wayland.windowManager.hyprland.settings = {
layerrule = [
"match:namespace vicinae, blur true, ignore_alpha 0.0, no_anim true"
# Blur and transparency for vicinae
"blur, vicinae"
"ignorealpha 0, vicinae"
# Disable animation for vicinae
"noanim, vicinae"
];
};
}
+4 -10
View File
@@ -1,17 +1,13 @@
{myConfig, ...}: {
{
wayland.windowManager.hyprland.settings = {
misc = {
disable_hyprland_logo = true;
disable_splash_rendering = true;
focus_on_activate = true;
anr_missed_pings = 3;
on_focus_under_fullscreen = 1;
new_window_takes_over_fullscreen = 1;
};
# experimental = {
# hdr = true;
# };
cursor = {
no_hardware_cursors = true;
no_break_fs_vrr = true;
@@ -34,8 +30,7 @@
shake = {
enabled = true;
threshold = 4.0;
limit = 4.0;
timeout = 200;
factor = 1.5;
};
};
@@ -48,11 +43,10 @@
bar_color = "$surface_container_high";
bar_text_color = "$on_surface";
bar_text_size = 0;
bar_text_font = myConfig.font.sans;
bar_text_font = "Sans";
bar_button_padding = 4;
bar_padding = 8;
bar_precedence_over_border = true;
on_double_click = "hyprctl dispatch fullscreen 1";
hyprbars-button = [
"$error, 10, , hyprctl dispatch killactive"
"$tertiary, 10, , hyprctl dispatch fullscreen 1"
+20 -5
View File
@@ -1,11 +1,26 @@
{
wayland.windowManager.hyprland.settings = {
windowrule = [
# Make all inactive windows transparent
"match:class .*, opacity 1 0.8"
"match:class firefox, match:title (?i).*bitwarden.*, no_screen_share on"
];
workspace = [
];
windowrulev2 = [
# --- POPUP RULES (Wifi, BT, Audio) ---
"float, class:^(org\.hakase\.popup\..*)$"
"animation slide right, class:^(org\.hakase\.popup\..*)$"
"dimaround, class:^(org\.hakase\.popup\..*)$"
# --- WALLPAPER PICKER ---
"float, class:^(org\.hakase\.switch-wallpaper)$"
"float, initialTitle:^(Wallpaper Selector)$"
"center, class:^(org\.hakase\.switch-wallpaper)$"
"center, initialTitle:^(Wallpaper Selector)$"
"size 60% 60%, class:^(org\.hakase\.switch-wallpaper)$"
"size 60% 60%, initialTitle:^(Wallpaper Selector)$"
"dimaround, class:^(org\.hakase\.switch-wallpaper)$"
"dimaround, initialTitle:^(Wallpaper Selector)$"
# --- CAVA RULES ---
"workspace special:music silent, title:^(cava)$"
"workspace special:music silent, initialTitle:^(cava)$"
];
};
}
+2 -23
View File
@@ -19,38 +19,17 @@
$HYPRCTL dispatch togglespecialworkspace "''${workspace_name}"
$HYPRCTL dispatch workspace "''${chosen_workspace_num}"
$HYPRCTL dispatch split:workspace "''${chosen_workspace_num}"
else
echo "[LOG] workspace is not special"
$HYPRCTL dispatch workspace "''${chosen_workspace_num}"
$HYPRCTL dispatch split:workspace "''${chosen_workspace_num}"
exit 0
fi
exit 0
'';
# TODO: revise
hakase-focus-switch = pkgs.writeShellScriptBin "hakase-focus-switch" ''
HYPRCTL="${pkgs.hyprland}/bin/hyprctl"
JQ="${pkgs.jq}/bin/jq"
workspace_id=$($HYPRCTL activeworkspace -j | $JQ '.id')
active_window=$($HYPRCTL activewindow -j)
is_floating=$(echo "$active_window" | $JQ '.floating')
if [ "$is_floating" == "true" ]; then
target_addr=$($HYPRCTL clients -j | $JQ -r --argjson ws "$workspace_id" '[.[] | select(.workspace.id == $ws and .floating == false)] | .[0].address')
else
target_addr=$($HYPRCTL clients -j | $JQ -r --argjson ws "$workspace_id" '[.[] | select(.workspace.id == $ws and .floating == true)] | .[0].address')
fi
if [ "$target_addr" != "null" ] && [ -n "$target_addr" ]; then
$HYPRCTL dispatch focuswindow address:$target_addr
fi
'';
in {
home.packages = [
hakase-workspace-switch-force
hakase-focus-switch
];
}
-71
View File
@@ -1,71 +0,0 @@
{pkgs, ...}: let
hyprctl = "${pkgs.hyprland}/bin/hyprctl";
jq = "${pkgs.jq}/bin/jq";
socat = "${pkgs.socat}/bin/socat";
hypr-window-rules = pkgs.writeShellScriptBin "hypr-window-rules" ''
LOG=/tmp/hypr-window-rules.log
log() { echo "[$(date +%T)] $*" >> "$LOG"; }
handle() {
local event="$1"
case "$event" in
windowtitlev2*)
local data="''${event#windowtitlev2>>}"
local addr="0x''${data%%,*}"
local title="''${data#*,}"
if echo "$title" | grep -qi "bitwarden"; then
log "bitwarden title detected: addr=$addr title=$title"
local info
info=$(${hyprctl} clients -j | ${jq} -r --arg addr "$addr" \
'.[] | select(.address == $addr) | "\(.class)|\(.floating)"')
local class="''${info%|*}"
local floating="''${info#*|}"
log " -> class=$class floating=$floating"
if [[ "$class" == "firefox" && "$floating" == "false" ]]; then
${hyprctl} dispatch togglefloating "address:$addr"
local target_w=600
local target_h=800
local mon_id
mon_id=$(${hyprctl} clients -j | ${jq} -r --arg addr "$addr" \
'.[] | select(.address == $addr) | .monitor')
local center
center=$(${hyprctl} monitors -j | ${jq} -r \
--argjson id "$mon_id" --argjson tw "$target_w" --argjson th "$target_h" \
'.[] | select(.id == $id) |
"\(.x + ((.width / .scale) - $tw) / 2 | floor)|\(.y + ((.height / .scale) - $th) / 2 | floor)"')
local cx="''${center%%|*}"
local cy="''${center#*|}"
${hyprctl} dispatch resizewindowpixel "exact $target_w $target_h, address:$addr"
${hyprctl} dispatch movewindowpixel "exact $cx $cy, address:$addr"
log " -> floated, resized to $target_w x $target_h, moved to $cx,$cy"
else
log " -> skipped (class or floating mismatch)"
fi
fi
;;
esac
}
log "started (HYPRLAND_INSTANCE_SIGNATURE=$HYPRLAND_INSTANCE_SIGNATURE)"
${socat} -u \
"UNIX-CONNECT:$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock" \
- \
| while IFS= read -r line; do handle "$line"; done
log "socat exited"
'';
in {
home.packages = [hypr-window-rules];
wayland.windowManager.hyprland.settings.exec-once = [
# FIXME: removed `hypr-window-rule` for excessive CPU usage. Reason unknown.
# "hypr-window-rules"
];
}
@@ -1,27 +0,0 @@
{pkgs, ...}: let
workspace-toggle = pkgs.writeShellScriptBin "workspace-toggle" ''
#!/usr/bin/env bash
target_workspace="$1"
# activeworkspace always returns the underlying workspace, even when a special
# workspace is open. Check the monitor's specialWorkspace field instead.
special=$(${pkgs.hyprland}/bin/hyprctl monitors -j | ${pkgs.jq}/bin/jq -r '.[] | select(.focused) | .specialWorkspace.name')
if [[ -n "$special" ]]; then
${pkgs.hyprland}/bin/hyprctl dispatch togglespecialworkspace "''${special#special:}"
current=$(${pkgs.hyprland}/bin/hyprctl activeworkspace -j | ${pkgs.jq}/bin/jq -r '.id')
if [[ $current -ne $target_workspace ]]; then
${pkgs.hyprland}/bin/hyprctl dispatch focusworkspaceoncurrentmonitor "$target_workspace"
fi
else
current=$(${pkgs.hyprland}/bin/hyprctl activeworkspace -j | ${pkgs.jq}/bin/jq -r '.id')
if [[ $current -eq $target_workspace ]]; then
${pkgs.hyprland}/bin/hyprctl dispatch workspace previous
else
${pkgs.hyprland}/bin/hyprctl dispatch split:workspace "$target_workspace"
fi
fi
'';
in {
home.packages = [workspace-toggle];
}
+16 -29
View File
@@ -1,45 +1,20 @@
{
config,
pkgs,
myConfig,
...
}: let
cacheWallpaper = "${config.home.homeDirectory}/.cache/current_wallpaper";
clockFont = myConfig.font.monospace;
scriptFont = myConfig.font.monospaceScript;
greetingConf = "${config.home.homeDirectory}/.cache/hyprlock-greeting.conf";
hakase-hyprlock = pkgs.writeShellScriptBin "hakase-hyprlock" ''
# Get focused monitor
monitor=$(hyprctl monitors -j | ${pkgs.jq}/bin/jq -r '.[] | select(.focused) | .name')
# Generate greeting label config
cat > ${greetingConf} << EOF
label {
monitor = $monitor
text = cmd[update:200] hakase-hyprlock-typewriter "\$(hakase-hyprlock-text-generator)"
color = \$on_surface_variant
font_size = 120
font_family = ${clockFont} Bold
position = 0, 480
halign = center
valign = center
}
EOF
exec hyprlock "$@"
'';
clockFont = "JetBrains Mono";
in {
imports = [
./scripts/typewriter.nix
./scripts/random-text.nix
];
home.packages = [hakase-hyprlock];
programs.hyprlock = {
# FIXME: `greeting` has as inconsistency in pos for different monitors
enable = true;
extraConfig = ''
source = ~/.config/hypr/hyprlock-colors.conf
source = ${greetingConf}
general {
hide_cursor = true
@@ -56,6 +31,18 @@ in {
vibrancy = 0.2
}
# Greeting (above clock)
label {
monitor = DP-1
text = cmd[update:1000] hakase-hyprlock-text-generator
color = $on_surface_variant
font_size = 120
font_family = ${clockFont} Bold
position = 0, 480
halign = center
valign = center
}
# Hours (top)
label {
monitor =
@@ -83,10 +70,10 @@ in {
# Date
label {
monitor =
text = cmd[update:60000] echo "<span font_features='ss02'>$(date '+%A, %B %d')</span>"
text = cmd[update:60000] date '+%A, %B %d'
color = $on_surface_variant
font_size = 18
font_family = ${clockFont} Italic
font_family = ${clockFont}
position = 0, -320
halign = center
valign = center
+8 -235
View File
@@ -1,243 +1,16 @@
{pkgs, ...}: let
hakase-hyprlock-text-generator = pkgs.writeShellScriptBin "hakase-hyprlock-text-generator" ''
cache_file="''${XDG_RUNTIME_DIR:-/tmp}/hyprlock_greeting"
pid_file="''${XDG_RUNTIME_DIR:-/tmp}/hyprlock_greeting_pid"
hour=$(date +%H)
name="$USER"
current_pid=$(pgrep -x hyprlock | head -1)
# Pick new greeting only when hyprlock restarts
if [[ -f $pid_file && -f $cache_file ]]; then
old_pid=$(cat "$pid_file")
if [[ "$old_pid" == "$current_pid" ]]; then
cat "$cache_file"
exit 0
fi
if [[ $hour -lt 12 ]]; then
greeting=""
elif [[ $hour -lt 18 ]]; then
greeting=""
else
greeting=""
fi
greetings=(
"Hello"
"Hola"
"Bonjour"
"Hallo"
"Ciao"
"Olá"
"Привет"
""
""
""
"مرحبا"
"שלום"
""
""
"Γειά σου"
"Merhaba"
"Xin chào"
"Cześć"
"Hej"
"Ahoj"
"Szia"
"Salut"
"Привіт"
""
""
"Jambo"
"Aloha"
"Sawubona"
"Hei"
"Hallå"
"Kamusta"
"Salam"
"Selamat"
"Saluton"
"Tere"
"Sveiki"
"Labas"
"Здраво"
"Здравей"
"Bok"
"Përshëndetje"
"Բարև"
""
"Сайн уу"
""
""
""
""
"Dia dhuit"
"Halò"
"Shwmae"
"Hoi"
"Halló"
"Kaixo"
"Bon dia"
"Ola"
"Ħello"
"ਿ "
" "
""
""
""
""
""
"Bawo"
"Ndeewo"
"Sannu"
"Iska warran"
"Kia ora"
"Bula"
"Talofa"
"Mālō e lelei"
""
""
"Yá'át'ééh"
"Allinllachu"
"Mba'éichapa"
"Salve"
"Moien"
"Apa khabar"
"Сәлем"
"Assalomu alaykum"
"Slav"
""
)
inspirations=(
"Dream Big"
"Stay True"
"Be Kind"
"Work Hard"
"Keep Going"
"Be Brave"
"Love Life"
"Stay Calm"
"Think Positive"
"Be Happy"
"No Fear"
"Have Faith"
"Trust Yourself"
"Focus Now"
"Take Action"
"Never Settle"
"Rise Up"
"Shine On"
"Stand Tall"
"Live Free"
"Just Begin"
"Create Joy"
"Stay Strong"
"Breathe Deep"
"Be Bold"
"Look Ahead"
"Move Forward"
"Aim High"
"Stay Humble"
"Find Peace"
"Do Good"
"Seek Truth"
"Love More"
"Be Yourself"
"Let Go"
"Keep Smiling"
"Stay Wild"
"Think Big"
"Be Awesome"
"Start Now"
"Enjoy Today"
"Choose Joy"
"Dream On"
"Fly High"
"Stay Focused"
"Be Fearless"
"Don't Stop"
"Make Waves"
"Be Original"
"Stay Curious"
"Be grateful"
"Keep pushing"
"Stay sharp"
"Why not?"
"Be still"
"Keep cool"
"Think twice"
"Be ready"
"Stay gold"
"Game on"
"Level up"
"Code on"
"Git commit"
"Hack on"
)
cyberpunk=(
"System: ONLINE"
"Encryption: ACTIVE"
"Access: GRANTED"
"Uptime: OPTIMAL"
"Link: ESTABLISHED"
"Protocol: SECURE"
"Daemon: WATCHING"
"Netrunner: READY"
"Signal: STRONG"
"Proxy: ENGAGED"
"Root: ACCESS"
"Kernel: PANIC"
)
yojijukugo=(
""
""
""
""
""
""
""
""
)
habits=(
"Check posture"
"Drink water"
"Shoulders down"
"Eyes off screen"
"Deep breath"
"Stretch now"
"Unclench jaw"
"Touch grass"
"Blink now"
"Stand up"
)
dev=(
"It works locally"
"Sudo please"
"Flake locked"
"Compiling..."
"Git push force"
"rm -rf /"
":q! to exit"
"Works on my machine"
"Coffee needed"
"Fixing bugs"
"Hello World"
"Null Pointer"
"Segfault"
)
# Combine all arrays
combined=(
"''${greetings[@]}"
"''${inspirations[@]}"
# "''${cyberpunk[@]}"
"''${yojijukugo[@]}"
"''${habits[@]}"
"''${dev[@]}"
)
idx=$((RANDOM % ''${#combined[@]}))
greeting="''${combined[$idx]}"
echo "$current_pid" > "$pid_file"
echo "$greeting" > "$cache_file"
echo "$greeting"
'';
in {
+1 -1
View File
@@ -37,7 +37,7 @@
echo "''${text:0:$letter}_"
else
# Toggle every 4 calls (at 200ms update = ~800ms blink)
if (((blink / 4) % 2 == 0)); then
if (((blink / 20) % 2 == 0)); then
echo "''${text}_"
else
echo "''${text}<span alpha=\"1%\">_</span>"
+5 -34
View File
@@ -22,24 +22,13 @@
fi
tmp_file=$(mktemp)
LAST_WALLPAPER_FILE="$HOME/.cache/last_wallpaper_path"
if [ -f "$LAST_WALLPAPER_FILE" ]; then
last_path=$(cat "$LAST_WALLPAPER_FILE")
if [ -f "$last_path" ]; then
yazi_target="$last_path"
fi
fi
if [ -z "$yazi_target" ]; then
yazi_target="$HOME/Pictures/Wallpapers"
if [ ! -d "$yazi_target" ]; then
yazi_target="$HOME"
fi
target_dir="$HOME/Pictures/Wallpapers"
if [ ! -d "$target_dir" ]; then
target_dir="$HOME"
fi
# Ensure we are in a terminal that supports yazi
${pkgs.yazi}/bin/yazi "$yazi_target" --chooser-file="$tmp_file"
${pkgs.yazi}/bin/yazi "$target_dir" --chooser-file="$tmp_file"
if [ ! -f "$tmp_file" ]; then
echo "No selection file created."
@@ -57,42 +46,24 @@
# Persistence logic
CACHE_FILE="$HOME/.cache/current_wallpaper"
cp "$WALLPAPER" "$CACHE_FILE"
echo "$WALLPAPER" > "$HOME/.cache/last_wallpaper_path"
# Reload hyprpaper
${pkgs.hyprland}/bin/hyprctl hyprpaper unload all
${pkgs.hyprland}/bin/hyprctl hyprpaper preload "$CACHE_FILE"
${pkgs.hyprland}/bin/hyprctl hyprpaper wallpaper ",$CACHE_FILE"
exec matugen image "$CACHE_FILE" --source-color-index 0
exec matugen image "$CACHE_FILE"
'';
in {
wayland.windowManager.hyprland.settings = {
exec-once = [
"uwsm app -- hyprpaper"
];
bindd = [
"SUPER CTRL, I, Switch Wallpaper, exec, hakase-wallpaper-switch"
];
windowrule = [
# --- WALLPAPER PICKER ---
"match:class ^(org\.hakase\.switch-wallpaper)$, float on"
"match:initial_title ^(Wallpaper Selector)$, float on"
"match:class ^(org\.hakase\.switch-wallpaper)$, center on"
"match:initial_title ^(Wallpaper Selector)$, center on"
"match:class ^(org\.hakase\.switch-wallpaper)$, size 60% 60%"
"match:initial_title ^(Wallpaper Selector)$, size 60% 60%"
"match:class ^(org\.hakase\.switch-wallpaper)$, dim_around on"
"match:initial_title ^(Wallpaper Selector)$, dim_around on"
];
};
services.hyprpaper = {
enable = true;
settings = {
splash = false;
preload = [cacheWallpaper];
wallpaper = [
",${cacheWallpaper}"
-81
View File
@@ -1,81 +0,0 @@
{pkgs, ...}: let
# Max window size (leave room for waybar/hyprbars)
maxW = 2800;
maxH = 1100;
swayimg-wrapper = pkgs.writeShellScriptBin "swayimg-wrapper" ''
if [ -z "$1" ]; then
exec ${pkgs.swayimg}/bin/swayimg
fi
# Get image dimensions
dims=$(${pkgs.file}/bin/file -b "$1" | ${pkgs.gnugrep}/bin/grep -oP '\d+ ?x ?\d+' | head -1 | tr -d ' ')
if [ -z "$dims" ]; then
# Fallback if file doesn't report dimensions
exec ${pkgs.swayimg}/bin/swayimg "$@"
fi
imgW=$(echo "$dims" | cut -dx -f1)
imgH=$(echo "$dims" | cut -dx -f2)
# Calculate scale to fit within max bounds while preserving aspect ratio
scaleW=$(echo "scale=4; ${toString maxW} / $imgW" | ${pkgs.bc}/bin/bc)
scaleH=$(echo "scale=4; ${toString maxH} / $imgH" | ${pkgs.bc}/bin/bc)
# Use the smaller scale factor
if [ $(echo "$scaleW < $scaleH" | ${pkgs.bc}/bin/bc) -eq 1 ]; then
scale=$scaleW
else
scale=$scaleH
fi
# Only scale down, not up
if [ $(echo "$scale >= 1" | ${pkgs.bc}/bin/bc) -eq 1 ]; then
exec ${pkgs.swayimg}/bin/swayimg "$@"
fi
# Calculate new size
newW=$(echo "$imgW * $scale / 1" | ${pkgs.bc}/bin/bc)
newH=$(echo "$imgH * $scale / 1" | ${pkgs.bc}/bin/bc)
exec ${pkgs.swayimg}/bin/swayimg --size="$newW,$newH" "$@"
'';
in {
home.packages = [pkgs.swayimg swayimg-wrapper];
xdg.mimeApps = {
enable = true;
defaultApplications = {
"image/png" = "swayimg-wrapper.desktop";
"image/jpeg" = "swayimg-wrapper.desktop";
"image/gif" = "swayimg-wrapper.desktop";
"image/webp" = "swayimg-wrapper.desktop";
"image/bmp" = "swayimg-wrapper.desktop";
"image/svg+xml" = "swayimg-wrapper.desktop";
"image/tiff" = "swayimg-wrapper.desktop";
};
};
xdg.desktopEntries.swayimg-wrapper = {
name = "Swayimg";
exec = "swayimg-wrapper %f";
terminal = false;
type = "Application";
mimeType = ["image/png" "image/jpeg" "image/gif" "image/webp" "image/bmp" "image/svg+xml" "image/tiff"];
};
# swayimg config
xdg.configFile."swayimg/config".text = ''
[viewer]
scale = fit
[info]
show = no
'';
wayland.windowManager.hyprland.settings.windowrule = [
# --- IMAGE VIEWER (swayimg) ---
"match:class ^(swayimg)$, float on"
"match:class ^(swayimg)$, center on"
];
}
-75
View File
@@ -1,75 +0,0 @@
{pkgs, ...}: {
services.jellyfin-mpv-shim = {
enable = true;
package = pkgs.jellyfin-mpv-shim;
mpvConfig = {
osc = false;
osd-bar = false;
load-scripts = true;
input-vo-keyboard = true;
input-default-bindings = true;
# Automatic subtitle selection logic:
# Prefer English subtitles
slang = "eng,en";
# Prefer Japanese/Non-English audio first (if that's what you usually watch)
# or just ensure English subs are picked when audio isn't English.
sub-auto = "fuzzy";
sub-visibility = "yes";
};
mpvBindings = {
"j" = "cycle sub";
"S-j" = "cycle sub rev";
"v" = "cycle sub-visibility";
};
settings = {
use_mpv_config = false;
enable_osc = false;
menu_mouse = true;
# Shim specific auto-sub logic
# "subs-fallback" is a known good setting for the shim to handle this
subtitle_color = "#FFFFFFFF";
subtitle_size = 100;
audio_output = "hdmi";
auto_play = true;
fullscreen = true;
player_name = "hakase";
remote_kbps = 100000;
local_kbps = 1000000;
};
};
# Modern OSC + Quality scripts
home.file.".config/jellyfin-mpv-shim/scripts/uosc" = {
source = "${pkgs.mpvScripts.uosc}/share/mpv/scripts/uosc";
};
home.file.".config/jellyfin-mpv-shim/scripts/thumbfast.lua" = {
source = "${pkgs.mpvScripts.thumbfast}/share/mpv/scripts/thumbfast.lua";
};
home.file.".config/jellyfin-mpv-shim/scripts/autocrop.lua" = {
source = "${pkgs.mpvScripts.autocrop}/share/mpv/scripts/autocrop.lua";
};
home.file.".config/jellyfin-mpv-shim/fonts" = {
source = "${pkgs.mpvScripts.uosc}/share/fonts";
recursive = true;
};
wayland.windowManager.hyprland.settings = {
exec-once = [ "systemctl --user start jellyfin-mpv-shim" ];
windowrule = [
# --- JELLYFIN MPV SHIM ---
"match:class ^(jellyfin-mpv-shim)$, float on"
"match:class ^(jellyfin-mpv-shim)$, center on"
"match:class ^(jellyfin-mpv-shim)$, size 70% 70%"
"match:class ^(jellyfin-mpv-shim)$, opacity 1.0 override 1.0 override"
"match:class ^(jellyfin-mpv-shim)$, idle_inhibit focus"
"match:class ^(jellyfin-mpv-shim)$, no_blur on"
];
};
}
-1
View File
@@ -1,6 +1,5 @@
{pkgs, ...}: {
home.packages = with pkgs; [
# FIXME: only dark mode works. use matugen
jellyfin-tui
];
}
-5
View File
@@ -1,5 +0,0 @@
{pkgs, ...}: {
home.packages = with pkgs; [
libreoffice-fresh
];
}
+23
View File
@@ -0,0 +1,23 @@
{pkgs, ...}: {
home.packages = with pkgs; [loupe];
xdg.mimeApps = {
enable = true;
defaultApplications = {
"image/png" = "org.gnome.Loupe.desktop";
"image/jpeg" = "org.gnome.Loupe.desktop";
"image/gif" = "org.gnome.Loupe.desktop";
"image/webp" = "org.gnome.Loupe.desktop";
"image/bmp" = "org.gnome.Loupe.desktop";
"image/svg+xml" = "org.gnome.Loupe.desktop";
"image/tiff" = "org.gnome.Loupe.desktop";
};
};
wayland.windowManager.hyprland.settings.windowrulev2 = [
# --- IMAGE VIEWER (Loupe) ---
"float, class:^(org\.gnome\.Loupe)$"
"center, class:^(org\.gnome\.Loupe)$"
"size 70% 70%, class:^(org\.gnome\.Loupe)$"
];
}
-9
View File
@@ -24,10 +24,6 @@ output_path = "~/.config/starship.toml"
input_path = "~/.config/matugen/templates/walker"
output_path = "~/.config/walker/themes/nixos/style.css"
[templates.zathura]
input_path = "~/.config/matugen/templates/zathura"
output_path = "~/.config/zathura/zathura-matugen"
[templates.pywalfox]
input_path = '~/.config/matugen/templates/firefox'
output_path = '~/.cache/wal/colors.json'
@@ -59,8 +55,3 @@ post_hook = "makoctl reload"
input_path = "~/.config/matugen/templates/vicinae"
output_path = "~/.local/share/vicinae/themes/matugen.toml"
post_hook = "vicinae theme set matugen"
[templates.theme-switch]
input_path = "~/.config/matugen/templates/theme-switch"
output_path = "~/.config/matugen/scripts/theme-switch.sh"
post_hook = "sh ~/.config/matugen/scripts/theme-switch.sh"
+6 -357
View File
@@ -1,350 +1,20 @@
{
pkgs,
inputs,
myConfig,
...
}: {
home.packages = with pkgs; [
inputs.matugen.packages.${pkgs.system}.default
dconf
matugen
psmisc # for killall
];
home.file.".config/matugen/config.toml" = {
source = ./config.toml;
};
# Copy static templates
home.file.".config/matugen/templates/theme-switch".text = ''
#!/bin/sh
# Generated by Matugen
# mode will be replaced by 'dark' or 'light'
MODE="{{mode}}"
if [ "$MODE" = "dark" ]; then
${pkgs.dconf}/bin/dconf write /org/gnome/desktop/interface/color-scheme "'prefer-dark'"
else
${pkgs.dconf}/bin/dconf write /org/gnome/desktop/interface/color-scheme "'prefer-light'"
fi
'';
home.file.".config/matugen/templates/cava".source = ./templates/cava;
home.file.".config/matugen/templates/firefox".source = ./templates/firefox;
home.file.".config/matugen/templates/ghostty".source = ./templates/ghostty;
home.file.".config/matugen/templates/gtk3".source = ./templates/gtk3;
home.file.".config/matugen/templates/gtk4".source = ./templates/gtk4;
home.file.".config/matugen/templates/hyprland".source = ./templates/hyprland;
home.file.".config/matugen/templates/hyprlock".source = ./templates/hyprlock;
home.file.".config/matugen/templates/starship".source = ./templates/starship;
home.file.".config/matugen/templates/waybar".source = ./templates/waybar;
home.file.".config/matugen/templates/zathura".source = ./templates/zathura;
home.file.".config/matugen/templates/vicinae".text = ''
# Vicinae Matugen Theme Template
[meta]
name = "Matugen"
description = "Material You theme generated by Matugen - {{mode}} variant"
variant = "{{mode}}"
# ============================================================================
# Typography
# ============================================================================
[typography]
font_family = "${myConfig.font.monospace}"
# ============================================================================
# Core Colors
# ============================================================================
[colors.core]
accent = "{{colors.primary.default.hex}}"
accent_foreground = "{{colors.on_primary.default.hex}}"
background = "{{colors.surface.default.hex}}"
foreground = "{{colors.on_surface.default.hex}}"
secondary_background = "{{colors.surface_container.default.hex}}"
border = "{{colors.outline_variant.default.hex}}"
# ============================================================================
# Window Borders
# ============================================================================
[colors.main_window]
border = "{{colors.outline_variant.default.hex}}"
[colors.settings_window]
border = "{{colors.outline.default.hex}}"
# ============================================================================
# Accent Palette
# ============================================================================
[colors.accents]
blue = "{{colors.primary.default.hex}}"
green = "{{colors.tertiary.default.hex}}"
magenta = "{{colors.secondary.default.hex}}"
orange = { name = "{{colors.error.default.hex}}", lighter = 40 }
red = "{{colors.error.default.hex}}"
yellow = { name = "{{colors.tertiary.default.hex}}", lighter = 80 }
cyan = { name = "{{colors.primary.default.hex}}", lighter = 50 }
purple = "{{colors.secondary.default.hex}}"
# ============================================================================
# Text System
# ============================================================================
[colors.text]
default = "{{colors.on_surface.default.hex}}"
muted = "{{colors.on_surface_variant.default.hex}}"
danger = "{{colors.error.default.hex}}"
success = "{{colors.tertiary.default.hex}}"
placeholder = { name = "{{colors.on_surface_variant.default.hex}}", opacity = 0.6 }
[colors.text.selection]
background = "{{colors.primary.default.hex}}"
foreground = "{{colors.on_primary.default.hex}}"
[colors.text.links]
default = "{{colors.primary.default.hex}}"
visited = { name = "{{colors.tertiary.default.hex}}", darker = 20 }
# ============================================================================
# Input Fields
# ============================================================================
[colors.input]
border = "{{colors.outline.default.hex}}"
border_focus = "{{colors.primary.default.hex}}"
border_error = "{{colors.error.default.hex}}"
# ============================================================================
# Buttons
# ============================================================================
[colors.button.primary]
background = "{{colors.surface_container_high.default.hex}}"
foreground = "{{colors.on_surface.default.hex}}"
[colors.button.primary.hover]
background = "{{colors.surface_container_highest.default.hex}}"
[colors.button.primary.focus]
outline = "{{colors.primary.default.hex}}"
# ============================================================================
# Lists
# ============================================================================
[colors.list.item.hover]
background = { name = "{{colors.primary_container.default.hex}}", opacity = 0.25 }
foreground = "{{colors.on_surface.default.hex}}"
[colors.list.item.selection]
background = { name = "{{colors.primary_container.default.hex}}", opacity = 0.50 }
foreground = "{{colors.on_primary_container.default.hex}}"
secondary_background = "{{colors.primary_container.default.hex}}"
secondary_foreground = "{{colors.on_primary_container.default.hex}}"
# ============================================================================
# Grid Items
# ============================================================================
[colors.grid.item]
background = "{{colors.surface_container.default.hex}}"
[colors.grid.item.hover]
outline = { name = "{{colors.secondary.default.hex}}", opacity = 0.8 }
[colors.grid.item.selection]
outline = { name = "{{colors.primary.default.hex}}" }
# ============================================================================
# Scrollbars
# ============================================================================
[colors.scrollbars]
background = { name = "{{colors.primary.default.hex}}", opacity = 0.2 }
# ============================================================================
# Loading States
# ============================================================================
[colors.loading]
bar = "{{colors.primary.default.hex}}"
spinner = "{{colors.primary.default.hex}}"
'';
# Generate templates with font interpolation
home.file.".config/matugen/templates/walker".text = ''
/* @import "../../../../../../../.config/omarchy/current/theme/walker.css"; */
/* Define Matugen Colors */
@define-color text {{colors.on_surface.default.hex}};
@define-color base {{colors.surface_container.default.hex}};
@define-color border {{colors.primary.default.hex}};
@define-color selected_text {{colors.primary.default.hex}};
@define-color background {{colors.surface.default.hex}};
* {
all: unset;
}
* {
font-family: ${myConfig.font.monospace};
font-size: 18px;
color: @text;
}
scrollbar {
opacity: 0;
}
.normal-icons {
-gtk-icon-size: 16px;
}
.large-icons {
-gtk-icon-size: 32px;
}
.box-wrapper {
background: alpha(@base, 0.95);
padding: 20px;
border: 2px solid @border;
}
.preview-box {
}
.box {
}
.search-container {
background: @base;
padding: 10px;
}
.input placeholder {
opacity: 0.5;
}
.input {
}
.input:focus,
.input:active {
box-shadow: none;
outline: none;
}
.content-container {
}
.placeholder {
}
.scroll {
}
.list {
}
child,
child > * {
}
child:hover .item-box {
}
child:selected .item-box {
}
child:selected .item-box * {
color: @selected_text;
}
.item-box {
padding-left: 14px;
}
.item-text-box {
all: unset;
padding: 14px 0;
}
.item-text {
}
.item-subtext {
font-size: 0px;
min-height: 0px;
margin: 0px;
padding: 0px;
}
.item-image {
margin-right: 14px;
-gtk-icon-transform: scale(0.9);
}
.current {
font-style: italic;
}
.keybind-hints {
background: @background;
padding: 10px;
margin-top: 10px;
}
.preview {
}
'';
home.file.".config/matugen/templates/mako".text = ''
# Mako notification daemon configuration
# Generated by matugen
# Appearance
font=${myConfig.font.sans} 11
width=350
height=150
margin=10
padding=15
border-size=2
border-radius=8
# Behavior
default-timeout=5000
ignore-timeout=false
layer=overlay
anchor=top-right
# Interaction
markup=true
actions=true
# Grouping
group-by=app-name
max-visible=5
sort=-time
# Theme colors from matugen
background-color=#{{colors.surface_container_high.default.hex_stripped}}
text-color=#{{colors.on_surface.default.hex_stripped}}
border-color=#{{colors.primary.default.hex_stripped}}
progress-color=over #{{colors.primary_container.default.hex_stripped}}
[urgency=low]
border-color=#{{colors.tertiary.default.hex_stripped}}
[urgency=normal]
border-color=#{{colors.primary.default.hex_stripped}}
[urgency=high]
border-color=#{{colors.error.default.hex_stripped}}
default-timeout=0
'';
home.file.".config/matugen/templates" = {
source = ./templates;
recursive = true;
};
# Qt theming - follow GTK theme
qt = {
@@ -352,20 +22,11 @@
platformTheme.name = "gtk";
};
dconf.settings = {
"org/gnome/desktop/interface" = {
color-scheme =
if myConfig.theme.mode == "dark"
then "prefer-dark"
else "prefer-light";
};
};
# GTK theming with adw-gtk3 and Matugen colors
gtk = {
enable = true;
theme = {
name = "adw-gtk3";
name = "adw-gtk3-dark";
package = pkgs.adw-gtk3;
};
iconTheme = {
@@ -373,19 +34,7 @@
package = pkgs.papirus-icon-theme;
};
gtk3.extraCss = ''@import url("colors.css");'';
gtk3.extraConfig = {
gtk-application-prefer-dark-theme =
if myConfig.theme.mode == "dark"
then 1
else 0;
};
gtk4.extraCss = ''@import url("colors.css");'';
gtk4.extraConfig = {
gtk-application-prefer-dark-theme =
if myConfig.theme.mode == "dark"
then 1
else 0;
};
};
programs.ghostty.settings.theme = "matugen";
-16
View File
@@ -76,19 +76,3 @@
@define-color dark_3 {{colors.surface_container.default.hex}};
@define-color dark_4 {{colors.surface_container_high.default.hex}};
@define-color dark_5 {{colors.surface_container_highest.default.hex}};
/* Sidebar Fixes */
.sidebar, .navigation-sidebar {
background-color: @view_bg_color;
color: @view_fg_color;
}
.sidebar list, .navigation-sidebar list {
background-color: transparent;
color: @view_fg_color;
}
filechooser .sidebar {
background-color: @view_bg_color;
color: @view_fg_color;
}
-16
View File
@@ -76,19 +76,3 @@
@define-color dark_3 {{colors.surface_container.default.hex}};
@define-color dark_4 {{colors.surface_container_high.default.hex}};
@define-color dark_5 {{colors.surface_container_highest.default.hex}};
/* Sidebar Fixes */
.sidebar, .navigation-sidebar {
background-color: @view_bg_color;
color: @view_fg_color;
}
.sidebar list, .navigation-sidebar list {
background-color: transparent;
color: @view_fg_color;
}
filechooser .sidebar {
background-color: @view_bg_color;
color: @view_fg_color;
}
+126
View File
@@ -0,0 +1,126 @@
# Vicinae Matugen Theme Template
[meta]
name = "Matugen"
description = "Material You theme generated by Matugen - {{mode}} variant"
variant = "{{mode}}"
# ============================================================================
# Core Colors
# ============================================================================
[colors.core]
accent = "{{colors.primary.default.hex}}"
accent_foreground = "{{colors.on_primary.default.hex}}"
background = "{{colors.surface.default.hex}}"
foreground = "{{colors.on_surface.default.hex}}"
secondary_background = "{{colors.surface_container.default.hex}}"
border = "{{colors.outline_variant.default.hex}}"
# ============================================================================
# Window Borders
# ============================================================================
[colors.main_window]
border = "{{colors.outline_variant.default.hex}}"
[colors.settings_window]
border = "{{colors.outline.default.hex}}"
# ============================================================================
# Accent Palette
# ============================================================================
[colors.accents]
blue = "{{colors.primary.default.hex}}"
green = "{{colors.tertiary.default.hex}}"
magenta = "{{colors.secondary.default.hex}}"
orange = { name = "{{colors.error.default.hex}}", lighter = 40 }
red = "{{colors.error.default.hex}}"
yellow = { name = "{{colors.tertiary.default.hex}}", lighter = 80 }
cyan = { name = "{{colors.primary.default.hex}}", lighter = 50 }
purple = "{{colors.secondary.default.hex}}"
# ============================================================================
# Text System
# ============================================================================
[colors.text]
default = "{{colors.on_surface.default.hex}}"
muted = "{{colors.on_surface_variant.default.hex}}"
danger = "{{colors.error.default.hex}}"
success = "{{colors.tertiary.default.hex}}"
placeholder = { name = "{{colors.on_surface_variant.default.hex}}", opacity = 0.6 }
[colors.text.selection]
background = "{{colors.primary.default.hex}}"
foreground = "{{colors.on_primary.default.hex}}"
[colors.text.links]
default = "{{colors.primary.default.hex}}"
visited = { name = "{{colors.tertiary.default.hex}}", darker = 20 }
# ============================================================================
# Input Fields
# ============================================================================
[colors.input]
border = "{{colors.outline.default.hex}}"
border_focus = "{{colors.primary.default.hex}}"
border_error = "{{colors.error.default.hex}}"
# ============================================================================
# Buttons
# ============================================================================
[colors.button.primary]
background = "{{colors.surface_container_high.default.hex}}"
foreground = "{{colors.on_surface.default.hex}}"
[colors.button.primary.hover]
background = "{{colors.surface_container_highest.default.hex}}"
[colors.button.primary.focus]
outline = "{{colors.primary.default.hex}}"
# ============================================================================
# Lists
# ============================================================================
[colors.list.item.hover]
background = { name = "{{colors.primary_container.default.hex}}", opacity = 0.25 }
foreground = "{{colors.on_surface.default.hex}}"
[colors.list.item.selection]
background = { name = "{{colors.primary_container.default.hex}}", opacity = 0.50 }
foreground = "{{colors.on_primary_container.default.hex}}"
secondary_background = "{{colors.primary_container.default.hex}}"
secondary_foreground = "{{colors.on_primary_container.default.hex}}"
# ============================================================================
# Grid Items
# ============================================================================
[colors.grid.item]
background = "{{colors.surface_container.default.hex}}"
[colors.grid.item.hover]
outline = { name = "{{colors.secondary.default.hex}}", opacity = 0.8 }
[colors.grid.item.selection]
outline = { name = "{{colors.primary.default.hex}}" }
# ============================================================================
# Scrollbars
# ============================================================================
[colors.scrollbars]
background = { name = "{{colors.primary.default.hex}}", opacity = 0.2 }
# ============================================================================
# Loading States
# ============================================================================
[colors.loading]
bar = "{{colors.primary.default.hex}}"
spinner = "{{colors.primary.default.hex}}"
-41
View File
@@ -1,41 +0,0 @@
set default-bg "#{{colors.surface.default.hex_stripped}}"
set default-fg "#{{colors.on_surface.default.hex_stripped}}"
set statusbar-bg "#{{colors.surface.default.hex_stripped}}"
set statusbar-fg "#{{colors.on_surface.default.hex_stripped}}"
set inputbar-bg "#{{colors.surface.default.hex_stripped}}"
set inputbar-fg "#{{colors.on_surface.default.hex_stripped}}"
set notification-bg "#{{colors.surface.default.hex_stripped}}"
set notification-fg "#{{colors.on_surface.default.hex_stripped}}"
set notification-error-bg "#{{colors.error.default.hex_stripped}}"
set notification-error-fg "#{{colors.on_error.default.hex_stripped}}"
set notification-warning-bg "#{{colors.tertiary.default.hex_stripped}}"
set notification-warning-fg "#{{colors.on_tertiary.default.hex_stripped}}"
set highlight-color "#{{colors.tertiary.default.hex_stripped}}"
set highlight-active-color "#{{colors.secondary.default.hex_stripped}}"
set completion-bg "#{{colors.surface.default.hex_stripped}}"
set completion-fg "#{{colors.on_surface.default.hex_stripped}}"
set completion-group-bg "#{{colors.surface.default.hex_stripped}}"
set completion-group-fg "#{{colors.on_surface.default.hex_stripped}}"
set completion-highlight-bg "#{{colors.on_surface.default.hex_stripped}}"
set completion-highlight-fg "#{{colors.surface.default.hex_stripped}}"
set index-bg "#{{colors.surface.default.hex_stripped}}"
set index-fg "#{{colors.on_surface.default.hex_stripped}}"
set index-active-bg "#{{colors.surface_container.default.hex_stripped}}"
set index-active-fg "#{{colors.on_surface.default.hex_stripped}}"
set render-loading-bg "#{{colors.surface.default.hex_stripped}}"
set render-loading-fg "#{{colors.on_surface.default.hex_stripped}}"
set recolor-lightcolor "#{{colors.surface.default.hex_stripped}}"
set recolor-darkcolor "#{{colors.on_surface.default.hex_stripped}}"
+1 -25
View File
@@ -1,22 +1,5 @@
{pkgs, ...}: {
programs.mpv = {
enable = true;
scripts = with pkgs.mpvScripts; [
uosc
thumbfast
];
config = {
# uosc provides its own UI
osc = "no";
osd-bar = "no";
border = "no";
# Subtitle preferences - prefer full subtitles over forced
# slang = "eng,en,enm"; # English subtitle preference order
# subs-fallback = "default"; # Use default if preferred not found
# sub-forced-events-only = "no"; # Don't limit to forced subtitle events
};
};
home.packages = with pkgs; [mpv];
xdg.mimeApps = {
enable = true;
@@ -29,11 +12,4 @@
"video/quicktime" = "mpv.desktop";
};
};
wayland.windowManager.hyprland.settings.windowrule = [
# --- VIDEO PLAYER (mpv) ---
"match:class ^(mpv)$, float on"
"match:class ^(mpv)$, center on"
"match:class ^(mpv)$, size 60% 70%"
];
}
-1
View File
@@ -5,7 +5,6 @@
...
}: {
home.packages = [
# FIXME: does not dynamically update with matugen when open
inputs.nixovim.packages.${pkgs.system}.full
];
}
-9
View File
@@ -1,9 +0,0 @@
{pkgs, ...}: {
home.packages = with pkgs; [
nextcloud-client
];
wayland.windowManager.hyprland.settings.exec-once = [
"uwsm app -- nextcloud --background"
];
}
-17
View File
@@ -1,17 +0,0 @@
{ pkgs }:
pkgs.stdenv.mkDerivation {
pname = "hakase-plymouth-theme";
version = "1.0";
src = ./themes/hakase;
installPhase = ''
mkdir -p $out/share/plymouth/themes/hakase
cp * $out/share/plymouth/themes/hakase/
# Patch the .plymouth file to point to the store path
sed -i "s@ImageDir=.*@ImageDir=$out/share/plymouth/themes/hakase@" $out/share/plymouth/themes/hakase/hakase.plymouth
sed -i "s@ScriptFile=.*@ScriptFile=$out/share/plymouth/themes/hakase/hakase.script@" $out/share/plymouth/themes/hakase/hakase.plymouth
'';
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 293 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 694 B

@@ -1,11 +0,0 @@
[Plymouth Theme]
Name=Omarchy
Description=Omarchy splash screen.
ModuleName=script
[script]
ImageDir=/usr/share/plymouth/themes/omarchy
ScriptFile=/usr/share/plymouth/themes/omarchy/omarchy.script
ConsoleLogBackgroundColor=0x1a1b26
MonospaceFont=Cantarell 11
Font=Cantarell 11
-257
View File
@@ -1,257 +0,0 @@
# Omarchy Plymouth Theme Script
Window.SetBackgroundTopColor(0.176, 0.067, 0.165);
Window.SetBackgroundBottomColor(0.176, 0.067, 0.165);
logo.image = Image("logo.png");
logo.sprite = Sprite(logo.image);
logo.sprite.SetX (Window.GetWidth() / 2 - logo.image.GetWidth() / 2);
logo.sprite.SetY (Window.GetHeight() / 2 - logo.image.GetHeight() / 2);
logo.sprite.SetOpacity (1);
# Use these to adjust the progress bar timing
global.fake_progress_limit = 0.7; # Target percentage for fake progress (0.0 to 1.0)
global.fake_progress_duration = 15.0; # Duration in seconds to reach limit
# Progress bar animation variables
global.fake_progress = 0.0;
global.real_progress = 0.0;
global.fake_progress_active = 0; # 0 / 1 boolean
global.animation_frame = 0;
global.fake_progress_start_time = 0; # Track when fake progress started
global.password_shown = 0; # Track if password dialog has been shown
global.max_progress = 0.0; # Track the maximum progress reached to prevent backwards movement
fun refresh_callback ()
{
global.animation_frame++;
# Animate fake progress to limit over time with easing
if (global.fake_progress_active == 1)
{
# Calculate elapsed time since start
elapsed_time = global.animation_frame / 50.0; # Convert frames to seconds (50 FPS)
# Calculate linear progress ratio (0 to 1) based on time
time_ratio = elapsed_time / global.fake_progress_duration;
if (time_ratio > 1.0)
time_ratio = 1.0;
# Apply easing curve: ease-out quadratic
# Formula: 1 - (1 - x)^2
eased_ratio = 1 - ((1 - time_ratio) * (1 - time_ratio));
# Calculate fake progress based on eased ratio
global.fake_progress = eased_ratio * global.fake_progress_limit;
# Update progress bar with fake progress
update_progress_bar(global.fake_progress);
}
}
Plymouth.SetRefreshFunction (refresh_callback);
#----------------------------------------- Helper Functions --------------------------------
fun update_progress_bar(progress)
{
# Only update if progress is moving forward
if (progress > global.max_progress)
{
global.max_progress = progress;
width = Math.Int(progress_bar.original_image.GetWidth() * progress);
if (width < 1) width = 1; # Ensure minimum width of 1 pixel
progress_bar.image = progress_bar.original_image.Scale(width, progress_bar.original_image.GetHeight());
progress_bar.sprite.SetImage(progress_bar.image);
}
}
fun show_progress_bar()
{
progress_box.sprite.SetOpacity(1);
progress_bar.sprite.SetOpacity(1);
}
fun hide_progress_bar()
{
progress_box.sprite.SetOpacity(0);
progress_bar.sprite.SetOpacity(0);
}
fun show_password_dialog()
{
lock.sprite.SetOpacity(1);
entry.sprite.SetOpacity(1);
}
fun hide_password_dialog()
{
lock.sprite.SetOpacity(0);
entry.sprite.SetOpacity(0);
for (index = 0; bullet.sprites[index]; index++)
bullet.sprites[index].SetOpacity(0);
}
fun start_fake_progress()
{
# Don't reset if we already have progress
if (global.max_progress == 0.0)
{
global.fake_progress = 0.0;
global.real_progress = 0.0;
update_progress_bar(0.0);
}
global.fake_progress_active = 1;
global.animation_frame = 0;
}
fun stop_fake_progress()
{
global.fake_progress_active = 0;
}
#----------------------------------------- Dialogue --------------------------------
lock.image = Image("lock.png");
entry.image = Image("entry.png");
bullet.image = Image("bullet.png");
entry.sprite = Sprite(entry.image);
entry.x = Window.GetWidth()/2 - entry.image.GetWidth() / 2;
entry.y = logo.sprite.GetY() + logo.image.GetHeight() + 40;
entry.sprite.SetPosition(entry.x, entry.y, 10001);
entry.sprite.SetOpacity(0);
# Scale lock to be slightly shorter than entry field height
# Original lock is 84x96, entry height determines scale
lock_height = entry.image.GetHeight() * 0.8;
lock_scale = lock_height / 96;
lock_width = 84 * lock_scale;
scaled_lock = lock.image.Scale(lock_width, lock_height);
lock.sprite = Sprite(scaled_lock);
lock.x = entry.x - lock_width - 15;
lock.y = entry.y + entry.image.GetHeight()/2 - lock_height/2;
lock.sprite.SetPosition(lock.x, lock.y, 10001);
lock.sprite.SetOpacity(0);
# Bullet array
bullet.sprites = [];
fun display_normal_callback ()
{
hide_password_dialog();
# Get current mode
mode = Plymouth.GetMode();
# Only show progress bar for boot and resume modes
if ((mode == "boot" || mode == "resume") && global.password_shown == 1)
{
show_progress_bar();
start_fake_progress();
}
}
fun display_password_callback (prompt, bullets)
{
global.password_shown = 1; # Mark that password dialog has been shown
# Reset progress when password dialog appears
stop_fake_progress();
hide_progress_bar();
global.max_progress = 0.0;
global.fake_progress = 0.0;
global.real_progress = 0.0;
show_password_dialog();
# Clear all bullets first
for (index = 0; bullet.sprites[index]; index++)
bullet.sprites[index].SetOpacity(0);
# Create and show bullets for current password (max 21)
max_bullets = 21;
bullets_to_show = bullets;
if (bullets_to_show > max_bullets)
bullets_to_show = max_bullets;
for (index = 0; index < bullets_to_show; index++)
{
if (!bullet.sprites[index])
{
# Scale bullet image to 7x7 pixels
scaled_bullet = bullet.image.Scale(7, 7);
bullet.sprites[index] = Sprite(scaled_bullet);
bullet.x = entry.x + 20 + index * (7 + 5);
bullet.y = entry.y + entry.image.GetHeight() / 2 - 3.5;
bullet.sprites[index].SetPosition(bullet.x, bullet.y, 10002);
}
bullet.sprites[index].SetOpacity(1);
}
}
Plymouth.SetDisplayNormalFunction(display_normal_callback);
Plymouth.SetDisplayPasswordFunction(display_password_callback);
#----------------------------------------- Progress Bar --------------------------------
progress_box.image = Image("progress_box.png");
progress_box.sprite = Sprite(progress_box.image);
progress_box.x = Window.GetWidth() / 2 - progress_box.image.GetWidth() / 2;
progress_box.y = entry.y + entry.image.GetHeight() / 2 - progress_box.image.GetHeight() / 2;
progress_box.sprite.SetPosition(progress_box.x, progress_box.y, 0);
progress_box.sprite.SetOpacity(0);
progress_bar.original_image = Image("progress_bar.png");
progress_bar.sprite = Sprite();
progress_bar.image = progress_bar.original_image.Scale(1, progress_bar.original_image.GetHeight());
progress_bar.x = Window.GetWidth() / 2 - progress_bar.original_image.GetWidth() / 2;
progress_bar.y = progress_box.y + (progress_box.image.GetHeight() - progress_bar.original_image.GetHeight()) / 2;
progress_bar.sprite.SetPosition(progress_bar.x, progress_bar.y, 1);
progress_bar.sprite.SetOpacity(0);
fun progress_callback (duration, progress)
{
global.real_progress = progress;
# If real progress is above limit, stop fake progress and use real progress
if (progress > global.fake_progress_limit)
{
stop_fake_progress();
update_progress_bar(progress);
}
}
Plymouth.SetBootProgressFunction(progress_callback);
#----------------------------------------- Quit --------------------------------
fun quit_callback ()
{
logo.sprite.SetOpacity (1);
}
Plymouth.SetQuitFunction(quit_callback);
#----------------------------------------- Message --------------------------------
message_sprite = Sprite();
message_sprite.SetPosition(10, 10, 10000);
fun display_message_callback (text)
{
my_image = Image.Text(text, 1, 1, 1);
message_sprite.SetImage(my_image);
}
fun hide_message_callback (text)
{
message_sprite.SetOpacity(0);
}
Plymouth.SetDisplayMessageFunction (display_message_callback);
Plymouth.SetHideMessageFunction (hide_message_callback);
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 314 B

-4
View File
@@ -1,4 +0,0 @@
{pkgs, ...}: {
environment.systemPackages = with pkgs; [via];
services.udev.packages = with pkgs; [via];
}
+3 -10
View File
@@ -1,4 +1,4 @@
{pkgs, myConfig, ...}: let
{pkgs, ...}: let
# Screenshot script with swappy integration
screenshot = pkgs.writeShellScriptBin "screenshot" ''
#!/usr/bin/env bash
@@ -27,13 +27,8 @@
wl-copy < "$filepath"
notify-send "Screenshot saved" "Saved and copied to clipboard"
;;
ocr)
# OCR Selection
grim -g "$(slurp)" - | tesseract stdin stdout | wl-copy
notify-send "OCR" "Text extracted to clipboard"
;;
*)
echo "Usage: screenshot {region|window|screen|all|region-save|ocr}"
echo "Usage: screenshot {region|window|screen|all|region-save}"
exit 1
;;
esac
@@ -45,7 +40,6 @@ in {
swappy # Annotation tool
jq # For window selection
wl-clipboard # For copying to clipboard
tesseract # OCR tool
screenshot # Our wrapper script
];
@@ -60,7 +54,7 @@ in {
show_panel=true
line_size=5
text_size=20
text_font=${myConfig.font.sans}
text_font=sans-serif
paint_mode=brush
early_exit=false
fill_shape=false
@@ -72,6 +66,5 @@ in {
"SUPER SHIFT, S, Screenshot Active Window, exec, screenshot window"
"SUPER ALT, S, Quick Screenshot (no edit), exec, screenshot region-save"
"SUPER ALT SHIFT, S, Screenshot Current Monitor, exec, screenshot screen"
"SUPER ALT, E, OCR Selection, exec, screenshot ocr"
];
}
+5 -21
View File
@@ -1,33 +1,17 @@
{
pkgs,
lib,
...
}: {
{pkgs, ...}: {
services.swayosd.enable = true;
# Auto-restart swayosd on crash
systemd.user.services.swayosd = {
Unit = {
StartLimitBurst = lib.mkForce 5;
StartLimitIntervalSec = lib.mkForce 30;
After = [ "graphical-session.target" ];
PartOf = [ "graphical-session.target" ];
};
Service = {
Restart = lib.mkForce "on-failure";
RestartSec = lib.mkForce "1s";
};
Install.WantedBy = [ "graphical-session.target" ];
};
wayland.windowManager.hyprland.settings = {
exec-once = [
"uwsm app -- swayosd-server"
];
bindel = [
", XF86AudioRaiseVolume, exec, swayosd-client --output-volume raise"
", XF86AudioLowerVolume, exec, swayosd-client --output-volume lower"
];
bindl = [
", XF86AudioMute, exec, swayosd-client --output-volume mute-toggle"
", Caps_Lock, exec, sleep 0.1 && swayosd-client --caps-lock"
", Caps_Lock, exec, swayosd-client --caps-lock"
];
};
}
-5
View File
@@ -1,5 +0,0 @@
{ pkgs, ... }: {
home.packages = with pkgs; [
ttyper
];
}
+3 -35
View File
@@ -1,22 +1,5 @@
{
pkgs,
inputs,
...
}: let
vicinae-toggle = pkgs.writeShellScriptBin "vicinae-toggle" ''
VICINAE_BIN="${inputs.vicinae.packages.${pkgs.system}.default}/bin/vicinae"
ARGS=("$@")
if [ ''${#ARGS[@]} -eq 0 ]; then
ARGS=("toggle")
fi
if ! "$VICINAE_BIN" "''${ARGS[@]}" 2>/dev/null; then
${pkgs.systemd}/bin/systemctl --user restart vicinae || "$VICINAE_BIN" server &
sleep 0.4
exec "$VICINAE_BIN" "''${ARGS[@]}"
fi
'';
in {
{pkgs, ...}: {
# TODO: create a script that initializes vicinae if `vicinae server` is off.
services.vicinae = {
enable = true;
systemd = {
@@ -53,34 +36,19 @@ in {
"action.new" = "control+N";
"action.save" = "control+S";
};
theme = {
light = {
name = "matugen";
icon_theme = "Papirus-Dark";
};
dark = {
name = "matugen";
icon_theme = "Papirus-Dark";
};
};
};
};
# Ensure vicinae themes directory exists for matugen output
home.file.".local/share/vicinae/themes/.keep".text = "";
home.packages = [vicinae-toggle];
wayland.windowManager.hyprland.settings = {
exec-once = [
"vicinae server"
];
bindd = [
"SUPER, SPACE, Open Vicinae, exec, vicinae-toggle"
"SUPER, period, Open Emoji Picker, exec, vicinae-toggle deeplink vicinae://launch/core/search-emojis"
"SUPER, C, Open Calculator, exec, vicinae-toggle deeplink vicinae://launch/calculator/history"
"SUPER, V, Open Clipboard History, exec, vicinae-toggle deeplink vicinae://launch/clipboard/history"
"SUPER, SPACE, Open Vicinae, exec, vicinae toggle"
];
};
}
+49 -98
View File
@@ -4,75 +4,59 @@
myConfig,
...
}: let
# FIXME: waybar overlaps fullscreen display when restarting waybar
hakase-popup-launch = pkgs.writeShellScriptBin "hakase-popup-launch" ''
tui_name=$1
active_popup=$(${pkgs.hyprland}/bin/hyprctl clients -j | ${pkgs.jq}/bin/jq -r '.[] | select(.class | startswith("org.hakase.")) | .class')
tui_name=$1
active_popup=$(${pkgs.hyprland}/bin/hyprctl clients -j | ${pkgs.jq}/bin/jq -r '.[] | select(.class | startswith("org.hakase.")) | .class')
if [[ -z "''${tui_name}" ]]; then
echo "Usage: $(basename "$0") [tui-name]"
exit 1
fi
if [[ -z "''${tui_name}" ]]; then
echo "Usage: $(basename "$0") [tui-name]"
exit 1
fi
popup_checker() {
if [[ -z "$active_popup" ]]; then
echo "no_popup"
elif [[ "$active_popup" != "org.hakase.popup.''${tui_name}" ]]; then
echo "different"
else
echo "same"
fi
}
popup_checker() {
if [[ -z "$active_popup" ]]; then
echo "no_popup"
elif [[ "$active_popup" != "org.hakase.popup.''${tui_name}" ]]; then
echo "different"
else
echo "same"
fi
}
launch() {
exec ${pkgs.util-linux}/bin/setsid uwsm-app -- xdg-terminal-exec --app-id=org.hakase.popup."''${tui_name}" -e "''${tui_name}"
}
exec ${pkgs.util-linux}/bin/setsid uwsm-app -- xdg-terminal-exec --app-id=org.hakase.popup."''${tui_name}" -e "''${tui_name}"
}
focus() {
exec ${pkgs.hyprland}/bin/hyprctl dispatch focuswindow "class:org.hakase.popup.''${tui_name}"
}
focus() {
exec ${pkgs.hyprland}/bin/hyprctl dispatch focuswindow "class:org.hakase.popup.''${tui_name}"
}
replace() {
${pkgs.hyprland}/bin/hyprctl dispatch closewindow "class:''${active_popup}"
sleep 0.3
launch
}
replace() {
${pkgs.hyprland}/bin/hyprctl dispatch closewindow "class:''${active_popup}"
sleep 1
launch
}
run() {
local status
status=$(popup_checker)
run() {
local status
status=$(popup_checker)
if [[ "$status" == "no_popup" ]]; then
launch
elif [[ "$status" == "same" ]]; then
focus
elif [[ "$status" == "different" ]]; then
replace
fi
}
if [[ "$status" == "no_popup" ]]; then
launch
elif [[ "$status" == "same" ]]; then
focus
elif [[ "$status" == "different" ]]; then
replace
fi
}
run
run
'';
in {
wayland.windowManager.hyprland.settings = {
exec-once = [
"uwsm app -- waybar"
];
bind = [
"SUPER, Escape, exec, hakase-popup-launch btop"
"SUPER, N, exec, hakase-popup-launch impala"
"SUPER, B, exec, hakase-popup-launch bluetui"
"SUPER, T, exec, hakase-popup-launch wiremix"
];
windowrule = [
# --- POPUP RULES (Wifi, BT, Audio) ---
"match:class ^(org\.hakase\.popup\..*)$, float on"
"match:class ^(org\.hakase\.popup\..*)$, size 900 600"
"match:class ^(org\.hakase\.popup\..*)$, center on"
"match:class ^(org\.hakase\.popup\..*)$, animation slide right"
"match:class ^(org\.hakase\.popup\..*)$, dim_around on"
];
};
imports = [
./style.nix
@@ -116,38 +100,18 @@ in {
all-outputs = true;
format = "{icon}";
format-icons = {
"music" = "󰎆";
"gaming" = "󰊖";
"default" = "";
"active" = "󱓻";
# Numbered workspaces 1-5
"1" = "1";
"2" = "2";
"3" = "3";
"4" = "4";
"5" = "5";
# Kanji for workspaces 6-10
"6" = "1";
"7" = "2";
"8" = "3";
"9" = "4";
"10" = "5";
# Dice for workspaces 11-15
"11" = "1";
"12" = "2";
"13" = "3";
"14" = "4";
"15" = "5";
# Circled numbers for 16-20
"16" = "1";
"17" = "2";
"18" = "3";
"19" = "4";
"20" = "5";
"6" = "6";
"7" = "7";
"8" = "8";
"9" = "9";
"10" = "0";
"active" = "󱓻";
};
persistent-workspaces = {
"1" = [];
@@ -155,11 +119,6 @@ in {
"3" = [];
"4" = [];
"5" = [];
"6" = [];
"7" = [];
"8" = [];
"9" = [];
"10" = [];
};
};
@@ -168,34 +127,26 @@ in {
show-special = true;
special-visible-only = true;
all-outputs = true;
ignore-workspaces = ["^([0-9]+|gaming|music|jellyfin)$"];
ignore-workspaces = ["1" "2" "3" "4" "5" "6" "7" "8" "9" "10"];
format = "{icon}";
format-icons = {
"special:youtube" = "󰗃";
"special:music" = "󰎆";
"special:steam" = "󰓓";
"special:custom" = "󱗼";
"special:preload" = "󱗼";
"special:jellyfin" = "󰟞";
"jellyfin" = "󰟞";
"youtube" = "󰗃";
"steam" = "󰓓";
"custom" = "󱗼";
"preload" = "󱗼";
"default" = "󱗼";
};
};
"custom/omarchy" = {
format = "";
on-click = "vicinae-toggle";
on-click-right = "hyprctl dispatch overview:toggle";
on-click = "vicinae toggle"; # TODO: add fallback
on-click-right = "xdg-terminal-exec";
tooltip-format = "Omarchy Menu\n\nSuper + Alt + Space";
};
"cpu" = {
interval = 5;
format = "󰍛";
on-click = "hakase-popup-launch btop";
on-click = "hakase-focus-wrapper btop";
on-click-right = "xdg-terminal-exec";
};
+2 -18
View File
@@ -1,8 +1,4 @@
{
config,
myConfig,
...
}: {
{config, ...}: {
programs.waybar = {
style = ''
@import "matugen.css";
@@ -13,7 +9,7 @@
border: none;
border-radius: 0;
min-height: 0;
font-family: '${myConfig.font.monospace}';
font-family: 'JetBrainsMono Nerd Font';
font-size: 12px;
}
@@ -36,18 +32,6 @@
opacity: 0.5;
}
/* Add spacing separator every 5 workspaces */
#workspaces button:nth-child(5),
#workspaces button:nth-child(10),
#workspaces button:nth-child(15) {
margin-right: 10px;
}
/* Separator between normal and special workspaces */
#workspaces.special {
margin-left: 12px;
}
#cpu,
#battery,
#pulseaudio,
-5
View File
@@ -1,5 +0,0 @@
{
programs.wireshark.enable = true;
# dumpcap.enable = true;
usbmon.enable = true;
}
+4 -152
View File
@@ -1,162 +1,14 @@
{
pkgs,
myConfig,
...
}: let
# Yazi wrapper for xdg-desktop-portal-termfilechooser
# TODO: rewrite in the future
yaziWrapper = pkgs.writeShellScript "yazi-wrapper.sh" ''
if [[ "$6" == "1" ]]; then
set -x
fi
multiple="$1"
directory="$2"
save="$3"
path="$4"
out="$5"
termcmd="${pkgs.util-linux}/bin/setsid uwsm-app -- xdg-terminal-exec --app-id=org.hakase.popup.yazi -e"
cleanup() {
if [ -f "$tmpfile" ]; then
rm "$tmpfile" || :
fi
if [ "$save" = "1" ] && [ ! -s "$out" ]; then
rm "$path" || :
fi
}
trap cleanup EXIT HUP INT QUIT ABRT TERM
if [ "$save" = "1" ]; then
tmpfile=$(mktemp)
printf '%s' 'xdg-desktop-portal-termfilechooser saving files tutorial
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!! === WARNING! === !!!
!!! The contents of *whatever* file you open last in !!!
!!! yazi will be *overwritten*! !!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Instructions:
1) Move this file wherever you want.
2) Rename the file if needed.
3) Confirm your selection by opening the file, for
example by pressing <Enter>.
Notes:
1) This file is provided for your convenience. You can
only choose this placeholder file otherwise the save operation aborted.
2) If you quit yazi without opening a file, this file
will be removed and the save operation aborted.
' >"$path"
$termcmd ${pkgs.yazi}/bin/yazi --chooser-file="$tmpfile" "$path"
elif [ "$directory" = "1" ]; then
$termcmd ${pkgs.yazi}/bin/yazi --cwd-file="$out" "$path"
elif [ "$multiple" = "1" ]; then
$termcmd ${pkgs.yazi}/bin/yazi --chooser-file="$out" "$path"
else
$termcmd ${pkgs.yazi}/bin/yazi --chooser-file="$out" "$path"
fi
# Handle save file case
if [ "$save" = "1" ] && [ -s "$tmpfile" ]; then
selected_file=$(head -n 1 "$tmpfile")
if [ -f "$selected_file" ] && grep -qi "^xdg-desktop-portal-termfilechooser saving files tutorial" "$selected_file"; then
echo "$selected_file" >"$out"
fi
fi
'';
in {
wayland.windowManager.hyprland.settings = {
bindd = [
"SUPER, X, Open File Manager, exec, uwsm app -- yazi"
];
};
{pkgs, ...}: {
programs.yazi = {
enable = true;
enableFishIntegration = true;
settings = {
manager = {
show_hidden = false;
sort_by = "mtime";
sort_reverse = true;
sort_dir_first = false;
show_hidden = true;
sort_by = "natural";
sort_dir_first = true;
linemode = "size";
mouse_events = ["click" "scroll" "touch" "move" "drag"];
};
tasks = {
image_bound = [10000 10000];
};
opener = {
anki = [
{
run = "anki \"$@\"";
desc = "Open with Anki";
}
];
pdf = [
{
run = "zathura \"$@\"";
desc = "Open with Zathura";
}
{
run = "firefox \"$@\"";
desc = "Open with Firefox";
}
];
};
open = {
prepend_rules = [
{
name = "*.{apkg,colpkg}";
use = "anki";
}
{
mime = "application/pdf";
use = "pdf";
}
];
};
};
};
# Portal packages need to be in user profile for proper path resolution
home.packages = [
pkgs.xdg-desktop-portal-hyprland
pkgs.xdg-desktop-portal-gtk
pkgs.xdg-desktop-portal-termfilechooser
];
# xdg-desktop-portal-termfilechooser configuration
xdg.configFile."xdg-desktop-portal-termfilechooser/config".text = ''
[filechooser]
cmd=${yaziWrapper}
default_dir=$HOME/Downloads
'';
# Portal routing configuration - use termfilechooser for file dialogs
xdg.configFile."xdg-desktop-portal/portals.conf".text = ''
[preferred]
default=hyprland;gtk
org.freedesktop.impl.portal.FileChooser=termfilechooser
'';
xdg.mimeApps = {
enable = true;
defaultApplications = {
"inode/directory" = "yazi.desktop";
};
};
wayland.windowManager.hyprland.settings.windowrule = [
# File picker yazi - floating, centered, smaller size
"match:class ^(org\\.hakase\\.popup\\.yazi)$, float on"
"match:class ^(org\\.hakase\\.popup\\.yazi)$, size 60% 70%"
"match:class ^(org\\.hakase\\.popup\\.yazi)$, center on"
];
}
-38
View File
@@ -1,38 +0,0 @@
{
pkgs,
config,
lib,
...
}: {
home.packages = with pkgs; [
ocrmypdf
];
programs.zathura = {
enable = true;
options = {
selection-clipboard = "clipboard";
adjust-open = "best-fit";
pages-per-row = 1;
scroll-page-aware = "true";
scroll-full-overlap = "0.01";
scroll-step = 100;
zoom-min = 10;
recolor = true;
recolor-keephue = true;
};
extraConfig = "include ${config.home.homeDirectory}/.config/zathura/zathura-matugen";
};
home.activation.createZathuraMatugen = lib.hm.dag.entryAfter ["writeBoundary"] ''
if [ ! -f "${config.home.homeDirectory}/.config/zathura/zathura-matugen" ]; then
touch "${config.home.homeDirectory}/.config/zathura/zathura-matugen"
fi
'';
xdg.mimeApps = {
enable = true;
defaultApplications = {
"application/pdf" = "org.pwmt.zathura.desktop";
};
};
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 MiB

+44 -120
View File
@@ -1,127 +1,51 @@
{
hakase = {
myConfig = {
font = {
monospace = "MonoLisa";
monospaceScript = "MonoLisa Italic @ss02=1";
sans = "Sans";
};
nixos = {
username = "kenji";
hostname = "hakase";
timezone = "America/Chicago";
};
git = {
username = "kenji";
email = "kenji@hakase";
defaultBranch = "master";
};
theme = {
mode = "dark";
};
terminal = {
default = "ghostty";
font = "MonoLisa";
aliases = {
update = "sudo nixos-rebuild switch --flake ~/.config/nixos/#hakase";
};
};
btop = {
autostart = true;
monitor = "HDMI-A-1";
};
hyprland = {
monitors = [
# "DP-1,highres@180,0x1080,1,vrr,1,bitdepth,10,cm,hdr,sdrbrightness,2.5"
"DP-1,highres@180,0x1080,1,vrr,0"
"DP-2, highres@165,760x0,1"
"HDMI-A-1, highres@highrr@120, 3440x1440, 1.6"
];
wallpaper = "firewatch.png";
kb_options = "";
};
wakeup = {
mouse = {
disable = true;
vendor = "3710";
product = "5406";
};
};
firefox = {
bookmarks = [
{
name = "Home Manager";
url = "https://mynixos.com/home-manager/options/programs";
}
{
name = "YouTube";
url = "https://youtube.com";
}
{
name = "Nur";
url = "https://nur.nix-community.org/repos";
}
];
newtabpage = [
{
title = "Dashboard";
url = "https://dash.sakamoto.dev";
}
];
myConfig = {
nixos = {
username = "kenji";
hostname = "hakase";
timezone = "America/Chicago";
};
git = {
username = "kenji";
email = "kenji@hakase";
defaultBranch = "master";
};
terminal = {
default = "ghostty";
aliases = {
update = "sudo nixos-rebuild switch --flake ~/.config/nixos/#hakase";
};
};
};
hyprland = {
monitors = [
"DP-1,highres@180,0x1080,1,bitdepth,10,cm,hdr,sdrbrightness,1.4,sdrsaturation,0.98,vrr,0"
"DP-2, highres@165,760x0,1"
"HDMI-A-1, highres@highrr@120, 3440x1440, 1.6"
];
macbook = {
myConfig = {
font = {
monospace = "MonoLisa";
monospaceScript = "MonoLisa Italic @ss02=1";
sans = "Sans";
};
nixos = {
username = "kenji";
hostname = "macbook";
timezone = "America/Chicago";
};
git = {
username = "kenji";
email = "kenji@macbook";
defaultBranch = "master";
};
theme = {
mode = "dark";
};
terminal = {
default = "ghostty";
font = "MonoLisa";
aliases = {
update = "sudo nixos-rebuild switch --flake ~/.config/nixos/#macbook";
};
};
btop = {
autostart = false;
monitor = "eDP-1";
};
hyprland = {
# M1 Pro/Max/Air screens are usually built-in eDP-1.
# HiDPI scale 2.0 is safe for Retina.
monitors = [
"eDP-1, highres, auto, 2"
];
wallpaper = "firewatch.png";
kb_options = "";
};
firefox = {
bookmarks = [
{
name = "Asahi Linux";
url = "https://asahilinux.org/";
}
];
newtabpage = [];
};
wallpaper = "firewatch.png";
};
firefox = {
bookmarks = [
{
name = "Home Manager";
url = "https://mynixos.com/home-manager/options/programs";
}
{
name = "YouTube";
url = "https://youtube.com";
}
{
name = "Nur";
url = "https://nur.nix-community.org/repos";
}
];
newtabpage = [
{
title = "Dashboard";
url = "https://dash.sakamoto.dev";
}
];
};
};
}
Generated
+96 -317
View File
@@ -1,26 +1,5 @@
{
"nodes": {
"apple-silicon": {
"inputs": {
"flake-compat": "flake-compat",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1767637567,
"narHash": "sha256-njwPfL5gM/KRGLJ29CbQ4nLBoEkNPMvEHBAAPOP8BZc=",
"owner": "tpwrules",
"repo": "nixos-apple-silicon",
"rev": "530aa73aa9a21a078ff861b84767ae1d469715fa",
"type": "github"
},
"original": {
"owner": "tpwrules",
"repo": "nixos-apple-silicon",
"type": "github"
}
},
"aquamarine": {
"inputs": {
"hyprutils": [
@@ -41,11 +20,11 @@
]
},
"locked": {
"lastModified": 1778857089,
"narHash": "sha256-TclWRW2SdFeETLaiTG4BA8C8C4m/LppQEldncqyTzAQ=",
"lastModified": 1765900596,
"narHash": "sha256-+hn8v9jkkLP9m+o0Nm5SiEq10W0iWDSotH2XfjU45fA=",
"owner": "hyprwm",
"repo": "aquamarine",
"rev": "ab2b0af63fbc9fb779d684f19149b790978be8a8",
"rev": "d83c97f8f5c0aae553c1489c7d9eff3eadcadace",
"type": "github"
},
"original": {
@@ -124,32 +103,17 @@
}
},
"flake-compat": {
"locked": {
"lastModified": 1746162366,
"narHash": "sha256-5SSSZ/oQkwfcAz/o/6TlejlVGqeK08wyREBQ5qFFPhM=",
"owner": "nix-community",
"repo": "flake-compat",
"rev": "0f158086a2ecdbb138cd0429410e44994f1b7e4b",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "flake-compat",
"type": "github"
}
},
"flake-compat_2": {
"flake": false,
"locked": {
"lastModified": 1767039857,
"narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
"owner": "NixOS",
"lastModified": 1761588595,
"narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
"rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5",
"type": "github"
},
"original": {
"owner": "NixOS",
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
@@ -181,11 +145,11 @@
]
},
"locked": {
"lastModified": 1778716662,
"narHash": "sha256-m1Yf0wZ8j1OHjTc2UwHwyQRSnNeSgLJOd7q5Y45hzi4=",
"lastModified": 1765835352,
"narHash": "sha256-XswHlK/Qtjasvhd1nOa1e8MgZ8GS//jBoTqWtrS1Giw=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "f7c1a2d347e4c52d5fb8d10cb4d94b5884e546fb",
"rev": "a34fae9c08a15ad73f295041fec82323541400a9",
"type": "github"
},
"original": {
@@ -229,24 +193,6 @@
"url": "https://flakehub.com/f/DeterminateSystems/flake-schemas/%3D0.1.5.tar.gz"
}
},
"flake-utils": {
"inputs": {
"systems": "systems_6"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
@@ -310,27 +256,6 @@
"type": "github"
}
},
"hypr-dynamic-cursors": {
"inputs": {
"hyprland": [
"hyprland"
],
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1779050734,
"narHash": "sha256-uE/I8TrhVEyQJb8t+HeHNYQRv7VlwbZxXlTrMfP0x/A=",
"owner": "Virtcode",
"repo": "hypr-dynamic-cursors",
"rev": "39fe4ab66b45b011667f548d759d58e707521378",
"type": "github"
},
"original": {
"owner": "Virtcode",
"repo": "hypr-dynamic-cursors",
"type": "github"
}
},
"hyprcursor": {
"inputs": {
"hyprlang": [
@@ -347,11 +272,11 @@
]
},
"locked": {
"lastModified": 1776511930,
"narHash": "sha256-fCpwFiTW0rT7oKJqr3cqHMnkwypSwQKpbtUEtxdkgrM=",
"lastModified": 1753964049,
"narHash": "sha256-lIqabfBY7z/OANxHoPeIrDJrFyYy9jAM4GQLzZ2feCM=",
"owner": "hyprwm",
"repo": "hyprcursor",
"rev": "39435900785d0c560c6ae8777d29f28617d031ef",
"rev": "44e91d467bdad8dcf8bbd2ac7cf49972540980a5",
"type": "github"
},
"original": {
@@ -376,11 +301,11 @@
]
},
"locked": {
"lastModified": 1776426399,
"narHash": "sha256-RUESLKNikIeEq9ymGJ6nmcDXiSFQpUW1IhJ245nL3xM=",
"lastModified": 1763733840,
"narHash": "sha256-JnET78yl5RvpGuDQy3rCycOCkiKoLr5DN1fPhRNNMco=",
"owner": "hyprwm",
"repo": "hyprgraphics",
"rev": "68d064434787cf1ed4a2fe257c03c5f52f33cf84",
"rev": "8f1bec691b2d198c60cccabca7a94add2df4ed1a",
"type": "github"
},
"original": {
@@ -408,11 +333,11 @@
"xdph": "xdph"
},
"locked": {
"lastModified": 1779983308,
"narHash": "sha256-mvjt5EqRubXF5w1RnyLsWOduJQzHDZCjohWJz/TUvJM=",
"lastModified": 1767300597,
"narHash": "sha256-lGE1j1bEuNp7XoDP+oyyF/c+MzYAs6S+sz0NK71nXZE=",
"ref": "refs/heads/main",
"rev": "ebc1816dfb27f1091c9713876669e092a215382d",
"revCount": 7376,
"rev": "31d3181e1ee91e338fb4fb8207d64b8d689310fc",
"revCount": 6766,
"submodules": true,
"type": "git",
"url": "https://github.com/hyprwm/Hyprland"
@@ -456,11 +381,11 @@
]
},
"locked": {
"lastModified": 1776426575,
"narHash": "sha256-KI6nIfVihn/DPaeB5Et46Xg3dkNHrrEtUd5LBBVomB0=",
"lastModified": 1765643131,
"narHash": "sha256-CCGohW5EBIRy4B7vTyBMqPgsNcaNenVad/wszfddET0=",
"owner": "hyprwm",
"repo": "hyprland-guiutils",
"rev": "a968d211048e3ed538e47b84cb3649299578f19d",
"rev": "e50ae912813bdfa8372d62daf454f48d6df02297",
"type": "github"
},
"original": {
@@ -486,11 +411,11 @@
]
},
"locked": {
"lastModified": 1779209205,
"narHash": "sha256-asc7NpeB8vD66gvZeYcQkaWOs2X6Jgd29vBtP17vjxo=",
"lastModified": 1767304464,
"narHash": "sha256-HsdfmPf5291Y3yXScMoj53P/9SS1DK3KgbprBuR8A4k=",
"owner": "hyprwm",
"repo": "hyprland-plugins",
"rev": "1cb37fad68dff5f5840010c314fed5809b4ee66f",
"rev": "7a8521112361997d071fd1fef06d6becc7e53240",
"type": "github"
},
"original": {
@@ -511,11 +436,11 @@
]
},
"locked": {
"lastModified": 1772460177,
"narHash": "sha256-/6G/MsPvtn7bc4Y32pserBT/Z4SUUdBd4XYJpOEKVR4=",
"lastModified": 1765214753,
"narHash": "sha256-P9zdGXOzToJJgu5sVjv7oeOGPIIwrd9hAUAP3PsmBBs=",
"owner": "hyprwm",
"repo": "hyprland-protocols",
"rev": "1cb6db5fd6bb8aee419f4457402fa18293ace917",
"rev": "3f3860b869014c00e8b9e0528c7b4ddc335c21ab",
"type": "github"
},
"original": {
@@ -540,11 +465,11 @@
]
},
"locked": {
"lastModified": 1777320127,
"narHash": "sha256-Qu+Wf2Bp5qUjyn2YpZNq8a7JyzTGowhT1knrwE38a9U=",
"lastModified": 1764612430,
"narHash": "sha256-54ltTSbI6W+qYGMchAgCR6QnC1kOdKXN6X6pJhOWxFg=",
"owner": "hyprwm",
"repo": "hyprlang",
"rev": "090117506ddc3d7f26e650ff344d378c2ec329cc",
"rev": "0d00dc118981531aa731150b6ea551ef037acddd",
"type": "github"
},
"original": {
@@ -553,40 +478,18 @@
"type": "github"
}
},
"hyprspace": {
"inputs": {
"hyprland": [
"hyprland"
],
"systems": "systems_3"
},
"locked": {
"lastModified": 1775071961,
"narHash": "sha256-LXkeeH9Blr6ohS1LAsVZbkJ/EAkkMDATh5qu45hC7Zo=",
"owner": "KZDKM",
"repo": "Hyprspace",
"rev": "12ddde04f8584bf7de3151e6169918e0dda9f822",
"type": "github"
},
"original": {
"owner": "KZDKM",
"repo": "Hyprspace",
"type": "github"
}
},
"hyprsplit": {
"inputs": {
"hyprland": [
"hyprland"
],
"nixpkgs": "nixpkgs_2"
]
},
"locked": {
"lastModified": 1779414137,
"narHash": "sha256-XpwuFhwnfwPbzImZeUWWns///UEpoKNkpl1hN90C3Ag=",
"lastModified": 1766546378,
"narHash": "sha256-GSoSLHErh1mRfgXM57W98L67MMBHKCemHzxoZPrejSI=",
"owner": "shezdy",
"repo": "hyprsplit",
"rev": "0fc01e7930625ecb3e069f5dc8e1d61eab929f3b",
"rev": "9a8b55f4269bfa5c59d03ed9f4502f433572c616",
"type": "github"
},
"original": {
@@ -634,11 +537,11 @@
]
},
"locked": {
"lastModified": 1772462885,
"narHash": "sha256-5pHXrQK9zasMnIo6yME6EOXmWGFMSnCITcfKshhKJ9I=",
"lastModified": 1764592794,
"narHash": "sha256-7CcO+wbTJ1L1NBQHierHzheQGPWwkIQug/w+fhTAVuU=",
"owner": "hyprwm",
"repo": "hyprtoolkit",
"rev": "9af245a69fa6b286b88ddfc340afd288e00a6998",
"rev": "5cfe0743f0e608e1462972303778d8a0859ee63e",
"type": "github"
},
"original": {
@@ -659,11 +562,11 @@
]
},
"locked": {
"lastModified": 1779475241,
"narHash": "sha256-Nw4DN0A5krWNcPBvuWe5Gz2yuxsUUPiDgtu6SVPJQeU=",
"lastModified": 1766160771,
"narHash": "sha256-roINUGikWRqqgKrD4iotKbGj3ZKJl3hjMz5l/SyKrHw=",
"owner": "hyprwm",
"repo": "hyprutils",
"rev": "3cd3972b2ee658a14d2610d8494e09259e530124",
"rev": "5ac060bfcf2f12b3a6381156ebbc13826a05b09f",
"type": "github"
},
"original": {
@@ -684,11 +587,11 @@
]
},
"locked": {
"lastModified": 1777159683,
"narHash": "sha256-Jxixw6wZphUp+nHYxOKUYSckL17QMBx2d5Zp0rJHr1g=",
"lastModified": 1763640274,
"narHash": "sha256-Uan1Nl9i4TF/kyFoHnTq1bd/rsWh4GAK/9/jDqLbY5A=",
"owner": "hyprwm",
"repo": "hyprwayland-scanner",
"rev": "b8632713a6beaf28b56f2a7b0ab2fb7088dbb404",
"rev": "f6cf414ca0e16a4d30198fd670ec86df3c89f671",
"type": "github"
},
"original": {
@@ -713,11 +616,11 @@
]
},
"locked": {
"lastModified": 1778410714,
"narHash": "sha256-o6RzFj4nJXaPRY7EM01siuCQeT41RfwwmcmFQqwFJJg=",
"lastModified": 1766253200,
"narHash": "sha256-26qPwrd3od+xoYVywSB7hC2cz9ivN46VPLlrsXyGxvE=",
"owner": "hyprwm",
"repo": "hyprwire",
"rev": "85148a8e612808cf5ddb25d0b3c5840f3498a7dc",
"rev": "1079777525b30a947c8d657fac158e00ae85de9d",
"type": "github"
},
"original": {
@@ -748,27 +651,6 @@
"type": "github"
}
},
"matugen": {
"inputs": {
"nixpkgs": [
"nixpkgs"
],
"systems": "systems_4"
},
"locked": {
"lastModified": 1780068618,
"narHash": "sha256-LFiV5gdD4MkPrzBrc3Lq966vTQGuwwXC5WkgglWz7i4=",
"owner": "InioX",
"repo": "Matugen",
"rev": "74bfe9369a46589c5048072142796343a8d74168",
"type": "github"
},
"original": {
"owner": "InioX",
"repo": "Matugen",
"type": "github"
}
},
"nix-github-actions": {
"inputs": {
"nixpkgs": [
@@ -802,11 +684,11 @@
"rust-overlay": "rust-overlay_2"
},
"locked": {
"lastModified": 1779062503,
"narHash": "sha256-CYyaA/qV6TzccHJuEwi8LE9x/rVpMAFztsymq+HYsQ8=",
"lastModified": 1766882181,
"narHash": "sha256-Xmu3JL68gT623ySytIOoyKqoH0tj3qhtNOnT79RRews=",
"ref": "refs/heads/master",
"rev": "4fd264f24fdf87d701ec82e7c6a4ca3e15c1c0aa",
"revCount": 79,
"rev": "ddb728dae4c9d6842664395635c9d55fb65c8b56",
"revCount": 78,
"type": "git",
"url": "https://git.sakamoto.dev/kenji/nixovim.git"
},
@@ -817,16 +699,16 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1768127708,
"narHash": "sha256-1Sm77VfZh3mU0F5OqKABNLWxOuDeHIlcFjsXeeiPazs=",
"owner": "nixos",
"lastModified": 1744536153,
"narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "ffbc9f8cbaacfb331b6017d5a5abb21a492c9a38",
"rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
@@ -845,43 +727,11 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 1778869304,
"narHash": "sha256-30sZNZoA1cqF5JNO9fVX+wgiQYjB7HJqqJ4ztCDeBZE=",
"lastModified": 1766309749,
"narHash": "sha256-3xY8CZ4rSnQ0NqGhMKAy5vgC+2IVK0NoVEzDoOh4DA4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d233902339c02a9c334e7e593de68855ad26c4cb",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": {
"lastModified": 1744536153,
"narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_4": {
"locked": {
"lastModified": 1778869304,
"narHash": "sha256-30sZNZoA1cqF5JNO9fVX+wgiQYjB7HJqqJ4ztCDeBZE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d233902339c02a9c334e7e593de68855ad26c4cb",
"rev": "a6531044f6d0bef691ea18d4d4ce44d0daa6e816",
"type": "github"
},
"original": {
@@ -898,14 +748,14 @@
"nixovim",
"nixpkgs"
],
"systems": "systems_5"
"systems": "systems_3"
},
"locked": {
"lastModified": 1779023681,
"narHash": "sha256-K7RLGyiK3J6wHr/JDxXdlGF0+0DEsdBf1w9mXjSyL8I=",
"lastModified": 1766443759,
"narHash": "sha256-iGDhUPOPyY9NOTNHkhNzZKoz3+OlBNGg451qtvPq/Ic=",
"owner": "nix-community",
"repo": "nixvim",
"rev": "0d05726bfb060f6559f6d64c1d427f3663dba178",
"rev": "1787eeda5a2ce35bcd57dbb482718b0d897786ae",
"type": "github"
},
"original": {
@@ -937,7 +787,7 @@
},
"pre-commit-hooks": {
"inputs": {
"flake-compat": "flake-compat_2",
"flake-compat": "flake-compat",
"gitignore": "gitignore",
"nixpkgs": [
"hyprland",
@@ -945,11 +795,11 @@
]
},
"locked": {
"lastModified": 1778507602,
"narHash": "sha256-kTwur1wV+01SdqskVMSo6JMEpg71ps3HpbFY2GsflKs=",
"lastModified": 1765911976,
"narHash": "sha256-t3T/xm8zstHRLx+pIHxVpQTiySbKqcQbK+r+01XVKc0=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "61ab0e80d9c7ab14c256b5b453d8b3fb0189ba0a",
"rev": "b68b780b69702a090c8bb1b973bab13756cc7a27",
"type": "github"
},
"original": {
@@ -960,22 +810,17 @@
},
"root": {
"inputs": {
"apple-silicon": "apple-silicon",
"chaotic": "chaotic",
"elephant": "elephant",
"home-manager": "home-manager_2",
"hypr-dynamic-cursors": "hypr-dynamic-cursors",
"hyprland": "hyprland",
"hyprland-plugins": "hyprland-plugins",
"hyprspace": "hyprspace",
"hyprsplit": "hyprsplit",
"matugen": "matugen",
"nixovim": "nixovim",
"nixpkgs": "nixpkgs_4",
"nixpkgs": "nixpkgs_2",
"nur": "nur",
"sops-nix": "sops-nix",
"textfox": "textfox",
"unlisted-fonts": "unlisted-fonts",
"vicinae": "vicinae",
"walker": "walker"
}
@@ -1003,7 +848,7 @@
},
"rust-overlay_2": {
"inputs": {
"nixpkgs": "nixpkgs_3"
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1766544144,
@@ -1026,11 +871,11 @@
]
},
"locked": {
"lastModified": 1777944972,
"narHash": "sha256-VfGRo1qTBKOe3s2gOv8LSoA6Fk19PvBlwQ1ECN0Evn8=",
"lastModified": 1766289575,
"narHash": "sha256-BOKCwOQQIP4p9z8DasT5r+qjri3x7sPCOq+FTjY8Z+o=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "c591bf665727040c6cc5cb409079acb22dcce33c",
"rev": "9836912e37aef546029e48c8749834735a6b9dad",
"type": "github"
},
"original": {
@@ -1071,80 +916,35 @@
},
"systems_3": {
"locked": {
"lastModified": 1689347949,
"narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default-linux",
"rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default-linux",
"repo": "default",
"type": "github"
}
},
"systems_4": {
"locked": {
"lastModified": 1689347949,
"narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default-linux",
"rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default-linux",
"repo": "default",
"type": "github"
}
},
"systems_5": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_6": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_7": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_8": {
"locked": {
"lastModified": 1689347949,
"narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
@@ -1167,11 +967,11 @@
]
},
"locked": {
"lastModified": 1767427579,
"narHash": "sha256-q9aFfPohbMS6ehkQHReMeIjtld0wGiUsxlHoPRRvsp4=",
"lastModified": 1763730250,
"narHash": "sha256-OPlKRltdA2iIm70Nw/kWt5FnwxR1xmxC44tqGUX7Hro=",
"owner": "adriankarlen",
"repo": "textfox",
"rev": "29c31979e5583d9367247f0af8675f88482ff481",
"rev": "2f385d16abab56984b874627ca0dd4f3ca7ae4ac",
"type": "github"
},
"original": {
@@ -1180,40 +980,19 @@
"type": "github"
}
},
"unlisted-fonts": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1748987994,
"narHash": "sha256-13QQRwZx9tRDmL79+XBM1YaC4W68mVrVW2NCv2w25WA=",
"ref": "refs/heads/master",
"rev": "468d51f24d3dd22c543e657c359fb333ff4df726",
"revCount": 1,
"type": "git",
"url": "https://git.sakamoto.dev/kenji/nix-fonts.git"
},
"original": {
"type": "git",
"url": "https://git.sakamoto.dev/kenji/nix-fonts.git"
}
},
"vicinae": {
"inputs": {
"nixpkgs": [
"nixpkgs"
],
"systems": "systems_7"
"systems": "systems_4"
},
"locked": {
"lastModified": 1779832601,
"narHash": "sha256-/dtn1sOTEcb/rNInzkdnK8PNIIDfQi7fEJfQEq+Is4g=",
"lastModified": 1767353605,
"narHash": "sha256-j2nuPawvb33wjTV93htSiMRxGeTLLrKhwOEqmmTu5uY=",
"owner": "vicinaehq",
"repo": "vicinae",
"rev": "dc1f7d47725c68debdb31be26781a96c14bac059",
"rev": "d89a9c9656486de144fd035bea7c2ea3b97fedf8",
"type": "github"
},
"original": {
@@ -1230,7 +1009,7 @@
"nixpkgs": [
"nixpkgs"
],
"systems": "systems_8"
"systems": "systems_5"
},
"locked": {
"lastModified": 1766324177,
@@ -1274,11 +1053,11 @@
]
},
"locked": {
"lastModified": 1778265244,
"narHash": "sha256-8jlPtGSsv/CQY6tVVyLF4Jjd0gnS+Zbn9yk/V13A9nM=",
"lastModified": 1761431178,
"narHash": "sha256-xzjC1CV3+wpUQKNF+GnadnkeGUCJX+vgaWIZsnz9tzI=",
"owner": "hyprwm",
"repo": "xdg-desktop-portal-hyprland",
"rev": "813ea5ca9a1702a9a2d1f5836bc00172ef698968",
"rev": "4b8801228ff958d028f588f0c2b911dbf32297f9",
"type": "github"
},
"original": {
+8 -49
View File
@@ -34,14 +34,6 @@
url = "github:hyprwm/hyprland-plugins";
inputs.hyprland.follows = "hyprland";
};
hyprspace = {
url = "github:KZDKM/Hyprspace";
inputs.hyprland.follows = "hyprland";
};
hypr-dynamic-cursors = {
url = "github:Virtcode/hypr-dynamic-cursors";
inputs.hyprland.follows = "hyprland";
};
nixovim = {
# FIXME: treesitter does not install automatically (disabled due to read-only problems)
url = "git+https://git.sakamoto.dev/kenji/nixovim.git";
@@ -60,21 +52,6 @@
url = "github:vicinaehq/vicinae";
inputs.nixpkgs.follows = "nixpkgs";
};
apple-silicon = {
url = "github:tpwrules/nixos-apple-silicon";
inputs.nixpkgs.follows = "nixpkgs";
};
unlisted-fonts = {
url = "git+https://git.sakamoto.dev/kenji/nix-fonts.git";
inputs.nixpkgs.follows = "nixpkgs";
};
# TODO: unstable.nixpkgs `matugen` is stuck at v4.0.0
# may need to use `git` version first
matugen = {
url = "github:/InioX/Matugen";
inputs.nixpkgs.follows = "nixpkgs";
# ...
};
};
outputs = {
@@ -85,44 +62,26 @@
chaotic,
sops-nix,
textfox,
apple-silicon,
...
} @ inputs: let
allConfig = import ./config.nix;
config = import ./config.nix;
system = "x86_64-linux";
args =
{
inherit inputs system;
}
// config;
in {
nixosConfigurations = {
hakase = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
specialArgs =
{
inherit inputs;
system = "x86_64-linux";
}
// allConfig.hakase;
specialArgs = args;
modules = [
inputs.matugen.nixosModules.default
home-manager.nixosModules.home-manager
sops-nix.nixosModules.sops
chaotic.nixosModules.default
./hosts/hakase/configuration.nix
];
};
macbook = nixpkgs.lib.nixosSystem {
system = "aarch64-linux";
specialArgs =
{
inherit inputs;
system = "aarch64-linux";
}
// allConfig.macbook;
modules = [
home-manager.nixosModules.home-manager
sops-nix.nixosModules.sops
apple-silicon.nixosModules.apple-silicon-support
./hosts/macbook/configuration.nix
];
};
};
};
}
-1
View File
@@ -6,7 +6,6 @@
}: {
imports = [
../modules/home/terminal.nix
# ../modules/home/flatpak.nix
../modules/home/apps.nix
../modules/home/apps-optional.nix
../modules/home/hyprland.nix
-25
View File
@@ -1,25 +0,0 @@
{
pkgs,
inputs,
config,
...
}: {
imports = [
../modules/home/terminal.nix
../modules/home/apps.nix
../modules/home/apps-optional.nix
../modules/home/hyprland.nix
../modules/home/waybar.nix
../modules/home/theme.nix
../modules/home/music.nix
# No gaming.nix for MacBook
inputs.walker.homeManagerModules.default
inputs.sops-nix.homeManagerModules.sops
inputs.vicinae.homeManagerModules.default
];
home.sessionVariables = {
};
home.stateVersion = "25.05";
}
-2
View File
@@ -8,7 +8,5 @@
../../modules/nixos/default.nix
../../modules/nixos/hyprland.nix
../../modules/nixos/gaming.nix
../../modules/nixos/amd.nix
../../modules/nixos/amdcpu.nix
];
}
-24
View File
@@ -1,24 +0,0 @@
{
pkgs,
myConfig,
...
}: {
imports = [
./hardware-configuration.nix
../../modules/nixos/default.nix
../../modules/nixos/hyprland.nix
# No gaming.nix (Steam is x86 only)
# No amd.nix
];
# Apple Silicon specific hardware tweaks
hardware.asahi = {
# peripheralFirmwareDirectory = ./firmware; # If you have extracted firmware
useExperimentalGPUDriver = true;
experimentalGPUInstallMode = "replace";
};
# Bootloader for Asahi is usually systemd-boot or grub, but asahi-module handles m1n1
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = false; # Asahi often prefers this false to avoid bricking nvram
}
-30
View File
@@ -1,30 +0,0 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
imports =
[ (modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [ "usb_storage" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "/dev/disk/by-uuid/00000000-0000-0000-0000-000000000000";
fsType = "ext4";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/0000-0000";
fsType = "vfat";
};
swapDevices = [ ];
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux";
}
+1 -13
View File
@@ -1,21 +1,9 @@
{pkgs, ...}: {
{
imports = [
../../apps/btop
../../apps/bottom
../../apps/anki
../../apps/gemini
../../apps/jellyfin
../../apps/tickrs
../../apps/claude
../../apps/delfin
../../apps/jellyfin-mpv-shim
../../apps/nextcloud
../../apps/ttyper
../../apps/libreoffice
];
home.packages = with pkgs; [
chromium
imagemagick
hidapitester
];
}
+2 -2
View File
@@ -1,9 +1,9 @@
{
imports = [
../../apps/yazi
../../apps/gemini
../../apps/firefox
../../apps/imv
../../apps/zathura
../../apps/loupe
../../apps/mpv
../../apps/mako
# ../../apps/starship
-25
View File
@@ -1,25 +0,0 @@
{pkgs, ...}: let
flatpak-install = pkgs.writeShellScriptBin "flatpak-install" ''
flatpak install --user --bundle "$1"
echo
read -p "Press Enter to close..."
'';
in {
home.packages = [flatpak-install];
xdg.mimeApps = {
enable = true;
defaultApplications = {
"application/vnd.flatpak" = "flatpak-bundle-installer.desktop";
};
};
xdg.desktopEntries.flatpak-bundle-installer = {
name = "Flatpak Bundle Installer";
exec = "flatpak-install %f";
terminal = true;
noDisplay = true;
type = "Application";
mimeType = ["application/vnd.flatpak"];
};
}
+19 -103
View File
@@ -1,58 +1,8 @@
{
pkgs,
lib,
myConfig,
...
}: let
gamingMonitor = "DP-1";
gaming-focus = pkgs.writeShellScriptBin "gaming-focus" ''
# If already on gaming workspace on the gaming monitor, go back
current=$(${pkgs.hyprland}/bin/hyprctl activeworkspace -j | ${pkgs.jq}/bin/jq -r '.name')
focused=$(${pkgs.hyprland}/bin/hyprctl monitors -j | ${pkgs.jq}/bin/jq -r '.[] | select(.focused) | .name')
if [[ "$current" == "gaming" && "$focused" == "${gamingMonitor}" ]]; then
${pkgs.hyprland}/bin/hyprctl dispatch workspace previous
exit 0
fi
# Close special workspace on gaming monitor if open
special=$(${pkgs.hyprland}/bin/hyprctl monitors -j | ${pkgs.jq}/bin/jq -r '.[] | select(.name == "${gamingMonitor}") | .specialWorkspace.name')
if [[ -n "$special" ]]; then
# Gaming workspace is already underneath just close the special overlay
${pkgs.hyprland}/bin/hyprctl --batch "dispatch focusmonitor ${gamingMonitor};dispatch togglespecialworkspace ''${special#special:}"
else
${pkgs.hyprland}/bin/hyprctl --batch "dispatch focusmonitor ${gamingMonitor};dispatch workspace name:gaming"
fi
'';
# Games that should have `stayfocused` applied (to avoid multi-monitor focus issues)
stayFocusedGames = [
# "Deadlock"
# "project8"
# "citadel"
];
mkGameRules = selector: [
"match:${selector}, monitor ${gamingMonitor}"
"match:${selector}, fullscreen on"
"match:${selector}, immediate on"
"match:${selector}, tile on"
];
stayFocusedRules = lib.flatten (map (
game: [
"match:title ^(${game})$, stay_focused on"
"match:class ^(${game})$, stay_focused on"
]
)
stayFocusedGames);
in {
{pkgs, ...}: {
home.packages = with pkgs; [
protonup-qt
protontricks
mangohud
gaming-focus
# via
];
programs.mangohud = {
@@ -68,65 +18,31 @@ in {
};
wayland.windowManager.hyprland.settings = {
workspace = [
"name:gaming, monitor:${gamingMonitor}, default:true"
];
exec-once = [
"[workspace special:steam silent] steam"
"[workspace special:steam silent] uwsm app -- steam"
];
bindd = [
"SUPER, A, Toggle Steam, togglespecialworkspace, steam"
"SUPER SHIFT, A, Move to Steam Special Workspace, movetoworkspace, special:steam"
"SUPER, G, Switch to Gaming Workspace, exec, gaming-focus"
"SUPER SHIFT, G, Move to Gaming Workspace, movetoworkspace, name:gaming"
"SUPER, T, Toggle Steam, togglespecialworkspace, steam"
"SUPER SHIFT, T, Move to Steam Special Workspace, movetoworkspace, special:steam"
];
windowrule =
[
"match:class ^(steam)$, hyprbars:no_bar on"
"match:class ^(steam_app_\\d+)$, hyprbars:no_bar on"
windowrulev2 = [
# --- STEAM RULES ---
"workspace special:steam silent, class:^(steam)$"
"noinitialfocus, class:^(steam)$"
"suppressevent activate, class:^(steam)$"
# --- STEAM GENERAL RULES ---
# Default ALL steam class windows to float. This catches all dialogs & properties windows.
"match:class ^(steam)$, float on"
# Suppress focus stealing from dialogs/etc.
"match:class ^(steam)$, no_initial_focus on"
"match:class ^(steam)$, suppress_event activate fullscreen maximize"
# --- GAMING RULES ---
"fullscreen, class:^steam_app_\d+$"
"monitor 0, class:^steam_app_\d+$"
"workspace 1, class:^steam_app_\d+$"
# --- STEAM CLIENT OVERRIDE ---
# Override the float for the main Steam client, tile it, and move it to the special workspace.
"match:class ^(steam)$, tile on"
"match:class ^(steam)$, workspace special:steam"
# --- STEAM GAME OVERRIDES ---
# Override the float for actual games and move them to the gaming workspace.
# 1. Auto-detected steam_app games (like Deadlock).
"match:class ^(steam_app_\\d+)$, monitor ${gamingMonitor}"
"match:class ^(steam_app_\\d+)$, tile on"
"match:class ^(steam_app_\\d+)$, fullscreen on"
"match:class ^(steam_app_\\d+)$, immediate on"
"match:class ^(steam_app_\\d+)$, workspace name:gaming"
# 2. Behavior-detected manual games (e.g. ARC Raiders).
# This moves any steam game to the gaming workspace and tiles it when it becomes fullscreen.
"match:class ^(steam)$, match:fullscreen true, tile on"
"match:class ^(steam)$, match:fullscreen true, workspace name:gaming"
]
# Other auto-detected non-steam games
++ (mkGameRules "class ^(gamescope)$")
++ (mkGameRules "class ^(lutris)$")
++ (mkGameRules "class ^(heroic)$")
++ (mkGameRules "class ^wine-.*$")
++ (mkGameRules "title ^Wine .*$")
++ (mkGameRules "initial_title ^(?i)godot.*$")
# ++ [
# "monitor 0, initialTitle:^(?i)godot.*$"
# "fullscreen, initialTitle:^(?i)godot.*$"
# "tile, initialTitle:^(?i)godot.*$"
# ]
# Stayfocused rules
++ stayFocusedRules;
"fullscreen, class:^(gamescope)$"
"fullscreen, class:^(lutris)$"
"fullscreen, class:^(heroic)$"
"fullscreen, class:^wine-.*$"
"fullscreen, title:^Wine .*$"
];
};
}
+8 -8
View File
@@ -34,22 +34,22 @@ in {
wayland.windowManager.hyprland.settings = {
workspace = [
"name:music, on-created-empty:hakase-music-launch"
"special:music, on-created-empty:hakase-music-launch"
];
bindd = [
"SUPER, M, Switch to Music, workspace, name:music"
"SUPER SHIFT, M, Move to Music Workspace, movetoworkspace, name:music"
"SUPER, M, Toggle Music, togglespecialworkspace, music"
"SUPER SHIFT, M, Move to Music Special Workspace, movetoworkspace, special:music"
];
windowrule = [
windowrulev2 = [
# --- MUSIC RULES (Jellyfin-TUI) ---
"match:title ^(jellyfin-tui)$, workspace name:music silent"
"match:initial_title ^(jellyfin-tui)$, workspace name:music silent"
"workspace special:music silent, title:^(jellyfin-tui)$"
"workspace special:music silent, initialTitle:^(jellyfin-tui)$"
# --- CAVA RULES ---
"match:title ^(cava)$, workspace name:music silent"
"match:initial_title ^(cava)$, workspace name:music silent"
"workspace special:music silent, title:^(cava)$"
"workspace special:music silent, initialTitle:^(cava)$"
];
};
}
+4 -9
View File
@@ -1,18 +1,13 @@
{pkgs, ...}: {
{ pkgs, ... }:
{
imports = [
../../apps/matugen
];
home.pointerCursor = {
gtk.enable = true;
package = pkgs.bibata-cursors;
name = "Bibata-Modern-Ice";
package = pkgs.rose-pine-hyprcursor;
name = "rose-pine-hyprcursor";
size = 24;
};
wayland.windowManager.hyprland.settings = {
env = [
"HYPRCURSOR_THEME,Bibata-Modern-Ice"
"HYPRCURSOR_SIZE,24"
];
};
}
-4
View File
@@ -1,4 +0,0 @@
{pkgs, ...}: {
boot.kernelModules = ["zenpower"];
boot.blacklistedKernelModules = ["k10temp"];
}
-7
View File
@@ -1,7 +0,0 @@
{
imports = [
../../apps/qmk
./asrock-a620i.nix
# ../../apps/wireshark
];
}
-8
View File
@@ -1,8 +0,0 @@
{pkgs, ...}: {
# fan setup
programs.coolercontrol.enable = true;
boot.kernelModules = ["nct6683"];
boot.extraModprobeConfig = ''
options nct6683 force=1
'';
}
+7 -12
View File
@@ -2,12 +2,6 @@
boot = {
consoleLogLevel = 3;
initrd.verbose = false;
# Global kernel parameters
kernelParams = [
"usbcore.autosuspend=-1" # Disable USB autosuspend to fix keyboard wakeup issues
];
loader = {
timeout = 0;
systemd-boot = {
@@ -23,13 +17,14 @@
initrd = {
systemd.enable = true;
};
plymouth = {
enable = true;
themePackages = [
(pkgs.callPackage ../../apps/plymouth/theme.nix {})
];
theme = "hakase";
# themePackages = [
# (pkgs.adi1090x-plymouth-themes.override {
# selected_themes = ["circle_hud"];
# })
# ];
# theme = "circle_hud";
};
};
}
}
-15
View File
@@ -1,15 +0,0 @@
{ pkgs, ... }: {
# Install btop system-wide with ROCm support for GPU monitoring.
environment.systemPackages = [
(pkgs.btop.override { rocmSupport = true; })
];
# Create a security wrapper for btop to grant it capabilities
# to read CPU power information without running as root.
security.wrappers."btop-power" = {
source = "${pkgs.btop.override { rocmSupport = true; }}/bin/btop";
owner = "root";
group = "root";
capabilities = "cap_dac_read_search,cap_sys_ptrace+ep";
};
}
+1 -4
View File
@@ -1,9 +1,7 @@
{pkgs, ...}: {
imports = [
./apps-optional.nix
./amd.nix
./backlight.nix
./flatpak.nix
./btop.nix
./boot.nix
./fonts.nix
./hardware.nix
@@ -12,7 +10,6 @@
./kernel.nix
./nix.nix
./power.nix # TODO: this one has to be optional
./mouse-wakeup.nix
./programs.nix
./security.nix
./services.nix
-6
View File
@@ -1,6 +0,0 @@
{pkgs, ...}: {
services.flatpak.enable = true;
# GTK portal required by most Flatpak apps for file chooser and other dialogs
xdg.portal.extraPortals = [pkgs.xdg-desktop-portal-gtk];
}
+1 -7
View File
@@ -1,11 +1,5 @@
{
pkgs,
inputs,
...
}: {
{pkgs, ...}: {
fonts.packages = with pkgs; [
inputs.unlisted-fonts.packages.${pkgs.system}.monolisa
nerd-fonts.fira-code
nerd-fonts.jetbrains-mono
+2 -3
View File
@@ -8,9 +8,7 @@
hardware.steam-hardware.enable = true;
hardware.xpadneo.enable = true; # Xbox controllers via Bluetooth
hardware.uinput.enable = true;
services.udev.packages = [
pkgs.game-devices-udev-rules
];
# services.udev.packages = [pkgs.game-devices-udev-rules];
programs.steam = {
enable = true;
@@ -27,3 +25,4 @@
# Fix slow Steam Download speeds
services.resolved.enable = true;
}
+1 -1
View File
@@ -10,7 +10,7 @@
useGlobalPkgs = true;
useUserPackages = true;
extraSpecialArgs = specialArgs;
users.${myConfig.nixos.username} = import ../../home/${myConfig.nixos.hostname}.nix;
users.${myConfig.nixos.username} = import ../../home/hakase.nix;
};
imports = [
-8
View File
@@ -24,12 +24,4 @@
default = ["${myConfig.terminal.default}"];
};
};
# XDG Desktop Portal - portal packages are in home-manager for proper path resolution
xdg.portal.enable = true;
# Required for portal file chooser integration
environment.sessionVariables = {
GTK_USE_PORTAL = "1";
};
}
+2 -5
View File
@@ -4,12 +4,9 @@
kernelParams = [
"quiet"
"splash"
"boot.shell_on_fail"
"loglevel=3"
"rd.systemd.show_status=false"
"rd.udev.log_level=3"
"udev.log_priority=3"
"intremap=on"
"udev.log_priority=3"
"rd.systemd.show_status=auto"
# Security hardening
"slab_nomerge"
"init_on_alloc=1"
-14
View File
@@ -1,14 +0,0 @@
{ lib, myConfig, ... }:
with lib;
let
cfg = myConfig.wakeup.mouse or {};
in
{
config = mkIf (cfg.disable or false && cfg.vendor != null && cfg.product != null) {
services.udev.extraRules = ''
# Disable wakeup for mouse configured in config.nix
ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="${cfg.vendor}", ATTRS{idProduct}=="${cfg.product}", ATTR{power/wakeup}="disabled"
'';
};
}
+10 -4
View File
@@ -1,4 +1,10 @@
{
# This file is intentionally left blank.
# USB wakeup is now handled by modules/nixos/mouse-wakeup.nix
}
{pkgs, ...}: {
# USB wakeup configuration
# services.udev.extraRules = ''
# # Enable keyboard (NuPhy Air96 V2) wakeup from suspend
# ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="19f5", ATTRS{idProduct}=="3247", ATTR{power/wakeup}="enabled"
#
# # Disable mouse (Pulsar 8Kdx) wakeup from suspend
# ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="3710", ATTRS{idProduct}=="5406", ATTR{power/wakeup}="disabled"
# '';
}
+4 -12
View File
@@ -8,11 +8,11 @@
enable = true;
settings = {
initial_session = {
command = "${pkgs.uwsm}/bin/start-hyprland";
command = "${pkgs.hyprland}/bin/Hyprland";
user = "${myConfig.nixos.username}";
};
default_session = {
command = "${pkgs.tuigreet}/bin/tuigreet --time --remember --cmd start-hyprland";
command = "${pkgs.tuigreet}/bin/tuigreet --time --remember --cmd Hyprland";
};
};
};
@@ -24,19 +24,11 @@
gnome.gnome-keyring.enable = true;
# Complements printer support
printing = {
enable = true;
drivers = with pkgs; [
gutenprint
cups-filters
hplip
cups-browsed
];
};
printing.enable = true;
avahi = {
enable = true;
nssmdns4 = true;
openFirewall = true;
openFirewall = false;
};
pipewire = {
enable = true;
+3 -3
View File
@@ -5,12 +5,12 @@
...
}: {
users = {
mutableUsers = true;
mutableUsers = false;
users = {
${myConfig.nixos.username} = {
isNormalUser = true;
extraGroups = ["wheel" "networkmanager" "input" "video" "wireshark"];
initialPassword = "password";
extraGroups = ["wheel" "networkmanager" "input" "video"];
hashedPasswordFile = config.sops.secrets.default_password.path; # FIXME: may not work!
useDefaultShell = true;
};
};
-4
View File
@@ -3,9 +3,5 @@
git
cloudflared
cachix
appimage-run
python314
usbutils
wireshark
];
}
-30
View File
@@ -1,30 +0,0 @@
#!/usr/bin/env bash
# Get current workspace ID
workspace_id=$(hyprctl activeworkspace -j | jq '.id')
# Get active window info
active_window=$(hyprctl activewindow -j)
is_floating=$(echo "$active_window" | jq '.floating')
echo "Current Workspace: $workspace_id"
echo "Active Window Floating: $is_floating"
if [ "$is_floating" == "true" ]; then
echo "Switching to Tiled..."
# Find a tiled window on the current workspace
# We sort by focus history or just pick the first one
target_addr=$(hyprctl clients -j | jq -r --argjson ws "$workspace_id" '[.[] | select(.workspace.id == $ws and .floating == false)] | sort_by(.focusHistoryID) | .[0].address')
else
echo "Switching to Floating..."
# Find a floating window on the current workspace
target_addr=$(hyprctl clients -j | jq -r --argjson ws "$workspace_id" '[.[] | select(.workspace.id == $ws and .floating == true)] | sort_by(.focusHistoryID) | .[0].address')
fi
echo "Target Address: $target_addr"
if [ "$target_addr" != "null" ] && [ -n "$target_addr" ]; then
hyprctl dispatch focuswindow address:$target_addr
else
echo "No target window found."
fi
+1
View File
@@ -1,6 +1,7 @@
#!/usr/bin/env bash
hour=$(date +%H)
# TODO(human): Set your name here
name="kenji"
if [[ $hour -lt 12 ]]; then