15 Commits

17 changed files with 189 additions and 85 deletions

View File

@@ -258,9 +258,10 @@ Required behavior:
- A named scratchpad exists for spotify. - A named scratchpad exists for spotify.
- A named scratchpad exists for transmission. - A named scratchpad exists for transmission.
- A named scratchpad exists for volume. - A named scratchpad exists for volume.
- A named scratchpad exists for x.com.
- Scratchpads appear near-fullscreen and centered by default. - Scratchpads appear near-fullscreen and centered by default.
- The codex scratchpad can be tiled into the normal workspace when desired, - The codex, claude, and x.com scratchpads can be tiled into the normal
while retaining its summon/dismiss toggle. workspace when desired, while retaining their summon/dismiss toggles.
- Toggling a scratchpad deactivates fullscreen/tabbed state first. - Toggling a scratchpad deactivates fullscreen/tabbed state first.
- Floating scratchpads are hidden from normal workspace and window listings. - Floating scratchpads are hidden from normal workspace and window listings.
@@ -447,6 +448,7 @@ Required behavior:
- `Super+Alt+s` toggles the spotify scratchpad. - `Super+Alt+s` toggles the spotify scratchpad.
- `Super+Alt+t` toggles the transmission scratchpad. - `Super+Alt+t` toggles the transmission scratchpad.
- `Super+Alt+v` toggles the volume scratchpad. - `Super+Alt+v` toggles the volume scratchpad.
- `Super+Alt+x` toggles the x.com scratchpad.
Important behavior: Important behavior:

View File

@@ -11,6 +11,12 @@
- Create `.worktrees/` if needed before running `git worktree add`. - Create `.worktrees/` if needed before running `git worktree add`.
- Only use a non-`.worktrees/` location when the user explicitly asks for a different path. - Only use a non-`.worktrees/` location when the user explicitly asks for a different path.
## GitHub pull requests
- Default to creating pull requests as ready for review, not drafts.
- Do not add a `[codex]` prefix or any other agent/tool prefix to pull request titles.
- Create a draft pull request only when the user explicitly asks for a draft or when the remote platform requires draft status.
- If using a helper, skill, or CLI wrapper that defaults to draft PRs, override that default before creating the PR.
## NixOS workflow ## NixOS workflow
- This system is managed with a Nix flake at `/srv/dotfiles/nixos`. - This system is managed with a Nix flake at `/srv/dotfiles/nixos`.
- Use `just switch` from that directory for rebuilds instead of plain `nixos-rebuild`. - Use `just switch` from that directory for rebuilds instead of plain `nixos-rebuild`.

View File

@@ -19,6 +19,7 @@ Bundled helpers:
- Prioritize easy wins first (`nix-collect-garbage`, container prune, Cargo artifacts). - Prioritize easy wins first (`nix-collect-garbage`, container prune, Cargo artifacts).
- Propose destructive actions with expected impact before running them. - Propose destructive actions with expected impact before running them.
- Run destructive actions only after confirmation, unless the user explicitly requests immediate execution of obvious wins. - Run destructive actions only after confirmation, unless the user explicitly requests immediate execution of obvious wins.
- For Rust build artifacts, do not repeatedly ask for confirmation before deleting explicit directories literally named `target` after `rust_target_dirs.py delete` validates them. Cargo targets are rebuildable artifacts; when the user asks to clean Rust target directories, validate with the helper, delete with `--yes`, and report the reclaimed space.
- Capture new reusable findings by updating this skill before finishing. - Capture new reusable findings by updating this skill before finishing.
## Workflow ## Workflow
@@ -178,6 +179,7 @@ Machine-specific heavy hitters seen in practice:
- 2026-05-26 cleanup: when `cargo test` is actively running in `~/Projects/subtr-actor`, leave `subtr-actor/target` alone and delete only inactive Cargo-backed targets. Deleting `keepbook`, `rlru`, `rocket-sense`, `rumno`, and stale `subtr-actor/.worktrees/*/target` reclaimed about 24.5G by helper sizing. - 2026-05-26 cleanup: when `cargo test` is actively running in `~/Projects/subtr-actor`, leave `subtr-actor/target` alone and delete only inactive Cargo-backed targets. Deleting `keepbook`, `rlru`, `rocket-sense`, `rumno`, and stale `subtr-actor/.worktrees/*/target` reclaimed about 24.5G by helper sizing.
- 2026-05-26 cleanup: `~/Projects/nixpkgs/.worktrees/*/result` symlinks pinned several GiB of Nix closures, and clean registered nixpkgs worktrees were about 460M each. Removing stale `result` symlinks, running GC, and removing clean worktrees while preserving dirty ones moved `/` from 100% used to about 90% used. - 2026-05-26 cleanup: `~/Projects/nixpkgs/.worktrees/*/result` symlinks pinned several GiB of Nix closures, and clean registered nixpkgs worktrees were about 460M each. Removing stale `result` symlinks, running GC, and removing clean worktrees while preserving dirty ones moved `/` from 100% used to about 90% used.
- 2026-05-27 cleanup: under `~/Projects`, `hypr-workspace-history/target` can be a Rust-style build cache even though the guarded helper rejects it because no `Cargo.toml` is present; inspect and remove that explicit cache manually if present. Preserve `~/Projects/Hyprland/src/layout/target`, which is source code, not a build artifact. - 2026-05-27 cleanup: under `~/Projects`, `hypr-workspace-history/target` can be a Rust-style build cache even though the guarded helper rejects it because no `Cargo.toml` is present; inspect and remove that explicit cache manually if present. Preserve `~/Projects/Hyprland/src/layout/target`, which is source code, not a build artifact.
- 2026-06-18 cleanup: deleting helper-validated Rust targets under `.worktrees/*/target` and `.claude/worktrees/*/target`, plus stale `~/Projects/lastfm-edit/target`, removed 24 target directories totaling 67.1G by helper sizing and moved `/` from 99% used to 90% used. Remaining large targets were top-level project caches under `keepbook`, `rlru`, `subtr-actor`, `rocket-sense`, `rocket-sense-pr-73-ci`, `rocket-sense-subtr-viewer`, `rocket-sense-controlled-plays`, and `boxcars`.
## Step 5: `/nix/store` Deep Dive ## Step 5: `/nix/store` Deep Dive
@@ -248,7 +250,7 @@ nix-store --gc --print-roots | rg '/\\.direnv/flake-profile-' | awk -F' -> ' '{p
- Do not delete user files directly unless explicitly requested. - Do not delete user files directly unless explicitly requested.
- Prefer cleanup tools that understand ownership/metadata (`nix`, `docker`, `podman`, `cargo-sweep`) over `rm -rf`. - Prefer cleanup tools that understand ownership/metadata (`nix`, `docker`, `podman`, `cargo-sweep`) over `rm -rf`.
- For Rust build artifacts, deleting an explicit directory literally named `target` is acceptable when it is discovered by the bundled helper; Cargo will rebuild it. - For Rust build artifacts, deleting an explicit directory literally named `target` is acceptable when it is discovered and validated by the bundled helper; Cargo will rebuild it. Do not double-check with the user after helper validation when the active request is Rust target cleanup.
- Present a concise “proposed actions” list before high-impact deletes. - Present a concise “proposed actions” list before high-impact deletes.
- If uncertain whether data is needed, stop at investigation and ask. - If uncertain whether data is needed, stop at investigation and ask.

View File

@@ -88,17 +88,7 @@ function M.setup(ctx)
end end
local function setup_window_overview_bindings() local function setup_window_overview_bindings()
bind(main_mod .. " + SHIFT + C", hl.dsp.window.close(), desc("Close active window")) local function toggle_hyprtasking()
bind(main_mod .. " + SHIFT + Q", hl.dsp.exit(), desc("Exit Hyprland"))
bind(main_mod .. " + Tab", hyprexpo("toggle"), desc("Toggle hyprexpo workspace overview", overview_bind_opts))
bind(main_mod .. " + SHIFT + Tab", hyprwinview({
action = "show",
include_current_workspace = false,
start_in_filter_mode = true,
default_action = "bring",
}), desc("Show all-workspace window overview", overview_bind_opts))
bind(main_mod .. " + SHIFT + slash", hyprwinview({ action = "toggle-filter" }), desc("Toggle window overview filter", overview_bind_opts))
bind("ALT + Tab", function()
if hl.plugin and hl.plugin.hyprtasking and hl.plugin.hyprtasking.toggle then if hl.plugin and hl.plugin.hyprtasking and hl.plugin.hyprtasking.toggle then
hl.plugin.hyprtasking.toggle("cursor") hl.plugin.hyprtasking.toggle("cursor")
else else
@@ -110,8 +100,19 @@ function M.setup(ctx)
font_size = 13, font_size = 13,
}) })
end end
end, desc("Toggle hyprtasking workspace overview", overview_bind_opts)) end
bind("ALT + SHIFT + Tab", hyprexpo("on"), desc("Open hyprexpo workspace overview", overview_bind_opts))
bind(main_mod .. " + SHIFT + C", hl.dsp.window.close(), desc("Close active window"))
bind(main_mod .. " + SHIFT + Q", hl.dsp.exit(), desc("Exit Hyprland"))
bind(main_mod .. " + Tab", toggle_hyprtasking, desc("Toggle hyprtasking workspace overview", overview_bind_opts))
bind(main_mod .. " + SHIFT + Tab", hyprwinview({
action = "show",
include_current_workspace = false,
start_in_filter_mode = true,
default_action = "bring",
}), desc("Show all-workspace window overview", overview_bind_opts))
bind(main_mod .. " + SHIFT + slash", hyprwinview({ action = "toggle-filter" }), desc("Toggle window overview filter", overview_bind_opts))
bind("ALT + Tab", toggle_hyprtasking, desc("Toggle hyprtasking workspace overview", overview_bind_opts))
bind(main_mod .. " + G", hyprwinview({ bind(main_mod .. " + G", hyprwinview({
action = "show", action = "show",
start_in_filter_mode = true, start_in_filter_mode = true,
@@ -290,6 +291,9 @@ function M.setup(ctx)
bind(mod_alt .. " + V", function() bind(mod_alt .. " + V", function()
toggle_scratchpad("volume") toggle_scratchpad("volume")
end, desc("Toggle volume scratchpad")) end, desc("Toggle volume scratchpad"))
bind(mod_alt .. " + X", function()
toggle_scratchpad("x_com")
end, desc("Toggle X scratchpad"))
bind(mod_alt .. " + grave", function() bind(mod_alt .. " + grave", function()
toggle_scratchpad("dropdown") toggle_scratchpad("dropdown")
end, desc("Toggle dropdown scratchpad")) end, desc("Toggle dropdown scratchpad"))

View File

@@ -51,6 +51,12 @@ function M.setup(ctx)
command = "google-chrome-stable --profile-directory=Default --app=https://messages.google.com/web/conversations", command = "google-chrome-stable --profile-directory=Default --app=https://messages.google.com/web/conversations",
class = "chrome-messages.google.com", class = "chrome-messages.google.com",
}, },
x_com = {
command = "x-com-pwa",
classes = { "x-com-pwa", "chrome-x.com" },
title = "X",
allow_tiling = true,
},
transmission = { transmission = {
command = "transmission-gtk", command = "transmission-gtk",
class = "transmission-gtk", class = "transmission-gtk",

View File

@@ -89,6 +89,7 @@ function M.setup(ctx)
end end
if enable_hyprtasking and not verify_config then if enable_hyprtasking and not verify_config then
hl.plugin.load("/run/current-system/sw/lib/libhyprtasking.so") hl.plugin.load("/run/current-system/sw/lib/libhyprtasking.so")
os.execute("hyprctl eval 'hl.config({plugin={hyprtasking={full_render=true}}})' >/dev/null 2>&1 || true")
end end
if enable_hyprexpo and not enable_hyprtasking and not verify_config then if enable_hyprexpo and not enable_hyprtasking and not verify_config then
hl.plugin.load("/run/current-system/sw/lib/libhyprexpo.so") hl.plugin.load("/run/current-system/sw/lib/libhyprexpo.so")

View File

@@ -65,7 +65,7 @@ return {
-- hook fires on every popup commit). Re-enable once fixed upstream. -- hook fires on every popup commit). Re-enable once fixed upstream.
enable_hyprexpo = false, enable_hyprexpo = false,
enable_hyprwinview = true, enable_hyprwinview = true,
enable_hyprtasking = false, enable_hyprtasking = true,
enable_workspace_history = true, enable_workspace_history = true,
enable_hyprwobbly = true, enable_hyprwobbly = true,
enable_dynamic_cursors = true, enable_dynamic_cursors = true,

View File

@@ -147,6 +147,7 @@ spawnBindings =
, key (super .|. alt) xK_s (toggleScratchpad "spotify") , key (super .|. alt) xK_s (toggleScratchpad "spotify")
, key (super .|. alt) xK_t (toggleScratchpad "transmission") , key (super .|. alt) xK_t (toggleScratchpad "transmission")
, key (super .|. alt) xK_v (toggleScratchpad "volume") , key (super .|. alt) xK_v (toggleScratchpad "volume")
, key (super .|. alt) xK_x (toggleScratchpad "x-com")
, key (super .|. alt) xK_c (spawnAction "google-chrome-stable") , key (super .|. alt) xK_c (spawnAction "google-chrome-stable")
, key super xK_e (spawnAction "emacsclient --eval '(emacs-everywhere)'") , key super xK_e (spawnAction "emacsclient --eval '(emacs-everywhere)'")
, key (super .|. ctrl) xK_e (shiftFocusedToNextEmptyWorkspace False) , key (super .|. ctrl) xK_e (shiftFocusedToNextEmptyWorkspace False)
@@ -297,6 +298,8 @@ scratchpadDefinitions =
anyMatcher [titleContains "Transmission", appIdContains "transmission"] anyMatcher [titleContains "Transmission", appIdContains "transmission"]
, ScratchpadDefinition "volume" "pavucontrol" $ , ScratchpadDefinition "volume" "pavucontrol" $
anyMatcher [appIdMatches "Pavucontrol", appIdContains "pavucontrol"] anyMatcher [appIdMatches "Pavucontrol", appIdContains "pavucontrol"]
, ScratchpadDefinition "x-com" "x-com-pwa" $
anyMatcher [appIdMatches "x-com-pwa", appIdContains "chrome-x.com"]
] ]
anyMatcher :: [RiverWMWindowState -> Bool] -> RiverWMWindowState -> Bool anyMatcher :: [RiverWMWindowState -> Bool] -> RiverWMWindowState -> Bool

View File

@@ -244,6 +244,11 @@ slackSelector = className =? "Slack"
spotifySelector = className =? "Spotify" spotifySelector = className =? "Spotify"
transmissionSelector = fmap (isPrefixOf "Transmission") title transmissionSelector = fmap (isPrefixOf "Transmission") title
volumeSelector = className =? "Pavucontrol" volumeSelector = className =? "Pavucontrol"
xComSelector =
className =? "x-com-pwa"
<||> fmap ("chrome-x.com" `isInfixOf`) className
<||> (chromeSelectorBase <&&> title =? "X")
<||> fmap ("x.com" `isInfixOf`) title
virtualClasses = virtualClasses =
[ (chromeSelector, "Chrome") [ (chromeSelector, "Chrome")
@@ -261,6 +266,7 @@ slackCommand = "slack"
spotifyCommand = "spotify" spotifyCommand = "spotify"
transmissionCommand = "transmission-gtk" transmissionCommand = "transmission-gtk"
volumeCommand = "pavucontrol" volumeCommand = "pavucontrol"
xComCommand = "x-com-pwa"
-- Startup hook -- Startup hook
@@ -811,6 +817,7 @@ scratchpads =
, NS "spotify" spotifyCommand spotifySelector nearFullFloat , NS "spotify" spotifyCommand spotifySelector nearFullFloat
, NS "transmission" transmissionCommand transmissionSelector nearFullFloat , NS "transmission" transmissionCommand transmissionSelector nearFullFloat
, NS "volume" volumeCommand volumeSelector nearFullFloat , NS "volume" volumeCommand volumeSelector nearFullFloat
, NS "x-com" xComCommand xComSelector nearFullFloat
] ]
@@ -1018,6 +1025,7 @@ addKeys conf@XConfig { modMask = modm } =
, ((modalt, xK_s), doScratchpad "spotify") , ((modalt, xK_s), doScratchpad "spotify")
, ((modalt, xK_t), doScratchpad "transmission") , ((modalt, xK_t), doScratchpad "transmission")
, ((modalt, xK_v), doScratchpad "volume") , ((modalt, xK_v), doScratchpad "volume")
, ((modalt, xK_x), doScratchpad "x-com")
-- Specific program spawning -- Specific program spawning

View File

@@ -12,11 +12,7 @@ let
src = inputs.codex-desktop-linux; src = inputs.codex-desktop-linux;
patches = [ ./patches/codex-desktop-linux-gsettings-schemas.patch ]; patches = [ ./patches/codex-desktop-linux-gsettings-schemas.patch ];
}; };
claudeDesktopSource = pkgs.applyPatches { claudeDesktopSource = inputs.claude-desktop;
name = "claude-desktop-linux-patched";
src = inputs.claude-desktop;
patches = [ ./patches/claude-desktop-add-dir-multiple-matches.patch ];
};
claudeDesktopNodePty = pkgs.callPackage "${claudeDesktopSource}/nix/node-pty.nix" {}; claudeDesktopNodePty = pkgs.callPackage "${claudeDesktopSource}/nix/node-pty.nix" {};
claudeDesktop = pkgs.callPackage "${claudeDesktopSource}/nix/claude-desktop.nix" { claudeDesktop = pkgs.callPackage "${claudeDesktopSource}/nix/claude-desktop.nix" {
node-pty = claudeDesktopNodePty; node-pty = claudeDesktopNodePty;

View File

@@ -86,6 +86,34 @@
exec google-chrome-stable --profile-directory="$profile_dir" --new-window exec google-chrome-stable --profile-directory="$profile_dir" --new-window
''; '';
}; };
xComPwa = pkgs.writeShellApplication {
name = "x-com-pwa";
runtimeInputs = [
googleChromeCommandWrappers
pkgs.jq
];
text = ''
profile_args=()
local_state="''${CHROME_USER_DATA_DIR:-$HOME/.config/google-chrome}/Local State"
if [ -r "$local_state" ]; then
profile_dir="$(
jq -r '
(.profile.info_cache // {})
| to_entries
| sort_by(if .key == "Default" then 0 else 1 end, -(.value.active_time // 0))
| .[0].key // empty
' "$local_state" 2>/dev/null || true
)"
if [ -n "$profile_dir" ]; then
profile_args+=(--profile-directory="$profile_dir")
fi
fi
exec google-chrome-stable "''${profile_args[@]}" --class=x-com-pwa --app=https://x.com/
'';
};
googleChromeDesktopEntries = pkgs.runCommand "google-chrome-desktop-entries" {nativeBuildInputs = [pkgs.gnused];} '' googleChromeDesktopEntries = pkgs.runCommand "google-chrome-desktop-entries" {nativeBuildInputs = [pkgs.gnused];} ''
mkdir -p "$out/share/applications" mkdir -p "$out/share/applications"
@@ -242,6 +270,21 @@
}; };
}; };
xdg.desktopEntries.x-com-pwa = {
name = "X";
genericName = "Social Network";
comment = "Open x.com in a dedicated Chrome app window";
icon = "google-chrome";
terminal = false;
type = "Application";
categories = ["Network"];
startupNotify = true;
exec = "${xComPwa}/bin/x-com-pwa";
settings = {
StartupWMClass = "x-com-pwa";
};
};
xdg.configFile."ghostty/config" = { xdg.configFile."ghostty/config" = {
force = true; force = true;
text = '' text = ''
@@ -354,6 +397,7 @@
spotify spotify
spotifyWaylandPatch spotifyWaylandPatch
tor-browser tor-browser
xComPwa
# vscode # vscode
zulip zulip
] ]

47
nixos/flake.lock generated
View File

@@ -114,11 +114,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1781314818, "lastModified": 1781735477,
"narHash": "sha256-76EizPNWUOPLqwg6OP1KnX7XE7FEdrsJ2zQQaRKLYT4=", "narHash": "sha256-s66kETXt3w11uXH/njBfmmB1TOZn/MAmLL5VSqwOzqQ=",
"owner": "sadjow", "owner": "sadjow",
"repo": "claude-code-nix", "repo": "claude-code-nix",
"rev": "7c3c4413d8dbe29762fb5a9cb5443c3a72a9e18a", "rev": "9f444d93bf8029de1a9be31634be5a995ee5292c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -135,11 +135,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1781493849, "lastModified": 1781747722,
"narHash": "sha256-FIJdDGH1gb4HTppTTwJSSlH5xrKr8IfpinkAWpJUpto=", "narHash": "sha256-4aFy+NJ3aIVi7mIPLvIubnUuDy09FwDd+kG2QpagzCY=",
"owner": "aaddrick", "owner": "aaddrick",
"repo": "claude-desktop-debian", "repo": "claude-desktop-debian",
"rev": "2d1d0c59ffb94c0de8a0c5627d03c28099599792", "rev": "748b38854841db29b122d17515d4cf5add598994",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -159,11 +159,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1781038009, "lastModified": 1781761441,
"narHash": "sha256-MxvxXJ+EJxB9On3VfwjHLfeZFSB8Xlqz1IRpl43F76Q=", "narHash": "sha256-ZXJdWelt7SwbQTh18krnNgSS2SRveK4aoqO3xPdODD8=",
"owner": "sadjow", "owner": "sadjow",
"repo": "codex-cli-nix", "repo": "codex-cli-nix",
"rev": "75d6b831e036029e3d5f60b4f128dc0121730c37", "rev": "e3e7751853ece92c2a05ba4e8feee54afdb668c8",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -183,16 +183,15 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1781231404, "lastModified": 1781785128,
"narHash": "sha256-RgbXa8W975nSV2zyQdcXjuQepahhlAF0cW6jwecU9x4=", "narHash": "sha256-GQXqQIYLBNnPZNrmgt7aedf7PvO4QKKYjpVCAfowbQg=",
"owner": "colonelpanic8", "owner": "ilysenko",
"repo": "codex-desktop-linux", "repo": "codex-desktop-linux",
"rev": "8b8c5f05774ec9a48664dcf657f9fb7761174f8c", "rev": "933413a679df51886ea05d1d0eeb8057e44bf764",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "colonelpanic8", "owner": "ilysenko",
"ref": "colonelpanic/linux-build-info-no-shadow",
"repo": "codex-desktop-linux", "repo": "codex-desktop-linux",
"type": "github" "type": "github"
} }
@@ -1150,11 +1149,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1781106993, "lastModified": 1781534922,
"narHash": "sha256-BddvyVeSgLZU34hzI4yaXYILmfQN9n7oQJk4RbSaZM4=", "narHash": "sha256-jmzKIyRmpZLpxnR7DsWZ42bMzt+WeYDk+/x3FKSkovM=",
"owner": "yerlotic", "owner": "yerlotic",
"repo": "hyprtasking", "repo": "hyprtasking",
"rev": "3b3cb9d0b2fd4f6f4227b5b9539e849a37a17ddd", "rev": "1a82ca1ac79602e3bfd5ecb0a52c40c2bf818586",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1409,11 +1408,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1781484243, "lastModified": 1781822941,
"narHash": "sha256-8MORYJdWu16cvjbdpUkql1CKU+49UYEBimhAeNHrba4=", "narHash": "sha256-9biXcoMW/Gdh7HBbXBpH2tt33xh8Zvhsm9wuHVEcpXE=",
"owner": "colonelpanic8", "owner": "colonelpanic8",
"repo": "keepbook", "repo": "keepbook",
"rev": "6a3381159a60761ac65ab0a1ebfd82762feae1b7", "rev": "815a26ff7efad93fd6fa5395af177c7c5d86068f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -1965,11 +1964,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1781557452, "lastModified": 1781930687,
"narHash": "sha256-SsVClSsfiSWNyf343bcCW/NZOgAgsSiYS8W2fmRXmmY=", "narHash": "sha256-DT8yGwCsJuKedNRXceXx681x8Y1Wz+41/n7zP8HlURA=",
"owner": "rlrml", "owner": "rlrml",
"repo": "rlru", "repo": "rlru",
"rev": "d815411d795110ab6e5beff33f59099322b94d00", "rev": "577eb6379e3adc0fd5e7bd9fb80556dc931c3e18",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@@ -275,7 +275,7 @@
}; };
codex-desktop-linux = { codex-desktop-linux = {
url = "github:colonelpanic8/codex-desktop-linux?ref=colonelpanic/linux-build-info-no-shadow"; url = "github:ilysenko/codex-desktop-linux";
inputs = { inputs = {
nixpkgs.follows = "nixpkgs"; nixpkgs.follows = "nixpkgs";
flake-utils.follows = "flake-utils"; flake-utils.follows = "flake-utils";

View File

@@ -198,6 +198,10 @@
src = inputs.hyprtasking; src = inputs.hyprtasking;
strictDeps = true; strictDeps = true;
postPatch = ''
substituteInPlace src/layout/layout_base.cpp \
--replace-fail 'e.element->passName()' 'e->element->passName()'
'';
nativeBuildInputs = nativeBuildInputs =
[ [
pkgs.pkg-config pkgs.pkg-config
@@ -287,10 +291,9 @@
hyprlandPluginPackages = hyprlandPluginPackages =
[ [
hyprNStack hyprNStack
hyprexpo
hyprwinview hyprwinview
hyprWorkspaceHistory hyprWorkspaceHistory
# hyprtasking # disabled: build failure against current Hyprland API hyprtasking
hyprDynamicCursors hyprDynamicCursors
hyprwobbly hyprwobbly
] ]

View File

@@ -204,6 +204,10 @@
src = inputs.hyprtasking; src = inputs.hyprtasking;
strictDeps = true; strictDeps = true;
postPatch = ''
substituteInPlace src/layout/layout_base.cpp \
--replace-fail 'e.element->passName()' 'e->element->passName()'
'';
nativeBuildInputs = [ nativeBuildInputs = [
pkgs.pkg-config pkgs.pkg-config
pkgs.meson pkgs.meson
@@ -291,10 +295,9 @@
hyprlandPluginPackages = hyprlandPluginPackages =
[ [
hyprNStack hyprNStack
hyprexpo
hyprwinview hyprwinview
hyprWorkspaceHistory hyprWorkspaceHistory
# hyprtasking # disabled: build failure against current Hyprland API hyprtasking
hyprDynamicCursors hyprDynamicCursors
hyprwobbly hyprwobbly
] ]

View File

@@ -107,6 +107,67 @@
services.nginx.virtualHosts."rocket-sense.duckdns.org" = { services.nginx.virtualHosts."rocket-sense.duckdns.org" = {
enableACME = true; enableACME = true;
forceSSL = true; forceSSL = true;
locations."= /privacy" = {
alias = pkgs.writeText "rocket-sense-privacy.html" ''
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Rocket Sense Privacy Policy</title>
<style>
body {
color: #171717;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
line-height: 1.55;
margin: 0;
padding: 48px 24px;
}
main {
max-width: 760px;
margin: 0 auto;
}
h1, h2 {
line-height: 1.2;
}
h1 {
font-size: 2rem;
}
h2 {
font-size: 1.2rem;
margin-top: 2rem;
}
</style>
</head>
<body>
<main>
<h1>Rocket Sense Privacy Policy</h1>
<p>Last updated: June 18, 2026</p>
<p>Rocket Sense is a Rocket League replay analysis service operated by Ivan Malison. This policy explains what information the service uses when you sign in and upload or view replay data.</p>
<h2>Information We Collect</h2>
<p>When you sign in with Epic Games, Rocket Sense receives the Epic account identifiers and profile fields that you approve during the Epic login flow, such as account ID and display name. When you use the service, Rocket Sense may store replay files, replay metadata, player identifiers, derived gameplay statistics, and basic account/session records needed to operate the site.</p>
<h2>How We Use Information</h2>
<p>Rocket Sense uses this information to authenticate users, associate uploads with accounts, process replay files, display replay-derived statistics, maintain site reliability, and prevent abuse.</p>
<h2>Sharing</h2>
<p>Rocket Sense does not sell personal information. Information may be processed by infrastructure providers used to host and operate the service, and may be disclosed if required by law or necessary to protect the service and its users.</p>
<h2>Retention</h2>
<p>Rocket Sense keeps account, replay, and derived analysis data for as long as needed to provide the service, debug issues, maintain security, or comply with legal obligations.</p>
<h2>Contact</h2>
<p>For privacy questions or deletion requests, contact Ivan Malison at IvanMalison@gmail.com.</p>
</main>
</body>
</html>
'';
extraConfig = ''
default_type text/html;
'';
};
locations."/" = { locations."/" = {
proxyPass = "http://127.0.0.1:30080"; proxyPass = "http://127.0.0.1:30080";
proxyWebsockets = true; proxyWebsockets = true;

View File

@@ -1,34 +0,0 @@
diff --git a/scripts/patches/config.sh b/scripts/patches/config.sh
index 2453488..7c3f510 100644
--- a/scripts/patches/config.sh
+++ b/scripts/patches/config.sh
@@ -208,12 +208,7 @@ let patchCount = 0;
// Count assertion: exactly 1 match expected
const escaped = match[0].replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
- const allMatches = code.match(new RegExp(escaped, 'g'));
- if (allMatches && allMatches.length > 1) {
- console.error('FATAL: --add-dir pattern matches ' +
- allMatches.length + ' times (expected 1).');
- process.exit(1);
- }
+ const replacementCount = (code.match(new RegExp(escaped, 'g')) || []).length;
let filtered;
if (variant === 'for-of') {
@@ -230,9 +225,12 @@ let patchCount = 0;
'.push("--add-dir",' + iterVar + '))';
}
- code = code.replace(match[0], filtered);
+ code = code.split(match[0]).join(filtered);
console.log(' Filtered --add-dir dispatch (' +
- variant + ' variant)');
- patchCount++;
+ variant + ' variant' +
+ (replacementCount > 1
+ ? ', ' + replacementCount + ' identical matches'
+ : '') + ')');
+ patchCount += Math.max(1, replacementCount);
}
// ================================================================