hypr: make Super+Alt+C toggle a runtime-selectable AI scratchpad

Super+Alt+C now toggles whichever AI app is currently selected (Codex or
Claude Desktop) instead of always Codex. The selection is read from
$XDG_STATE_HOME/hypr/ai-scratchpad at keypress time, so switching is
dynamic and needs no Hyprland reload.

Hyper+C opens a rofi chooser (rofi_ai_scratchpad.sh) to pick between the
two, replacing the old "Open Codex session menu" binding. It writes the
choice and brings the selected scratchpad into view.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-09 15:57:12 -07:00
parent ab49f6c079
commit 87422afae3
3 changed files with 92 additions and 4 deletions

View File

@@ -68,7 +68,7 @@ function M.setup(ctx)
bind(hyper .. " + V", exec([[cliphist list | rofi -dmenu -p "Clipboard" | cliphist decode | wl-copy]]), desc("Open clipboard history"))
bind(hyper .. " + P", exec("rofi-pass"), desc("Open password menu"))
bind(hyper .. " + N", exec("rofi_codex_desktop_project.sh"), desc("Start Codex Desktop thread from project"))
bind(hyper .. " + C", exec("rofi_tmcodex.sh"), desc("Open Codex session menu"))
bind(hyper .. " + C", exec("rofi_ai_scratchpad.sh"), desc("Choose AI scratchpad (Codex/Claude)"))
bind(hyper .. " + SHIFT + C", exec("rofi_tmcodex.sh resume"), desc("Resume Codex session"))
bind(hyper .. " + L", exec("hypr_rofi_layout"), desc("Open Hyprland layout menu"))
bind(hyper .. " + K", exec("rofi_kill_process.sh"), desc("Open process kill menu"))
@@ -264,9 +264,7 @@ function M.setup(ctx)
local function setup_scratchpad_bindings()
bind(main_mod .. " + SHIFT + X", hl.dsp.workspace.toggle_special("NSP"), desc("Toggle NSP special workspace"))
bind(mod_alt .. " + C", function()
toggle_scratchpad("codex")
end, desc("Toggle Codex scratchpad"))
bind(mod_alt .. " + C", toggle_active_ai_scratchpad, desc("Toggle AI scratchpad (Codex/Claude)"))
bind(mod_alt .. " + D", function()
toggle_scratchpad("discord")
end, desc("Toggle Discord scratchpad"))

View File

@@ -17,6 +17,11 @@ function M.setup(ctx)
class = "codex-desktop",
allow_tiling = true,
},
claude = {
command = "claude-desktop",
class = "claude-desktop",
allow_tiling = true,
},
htop = {
command = "alacritty --class htop-scratch --title htop -e htop",
class = "htop-scratch",
@@ -517,6 +522,49 @@ function M.setup(ctx)
end
end
-- Which AI scratchpad SUPER+ALT+C targets. Selected at runtime (no reload)
-- by rofi_ai_scratchpad.sh, which writes the chosen name to this file.
local ai_scratchpad_default = "codex"
local function ai_scratchpad_state_path()
local base = os.getenv("XDG_STATE_HOME") or ((os.getenv("HOME") or "") .. "/.local/state")
return base .. "/hypr/ai-scratchpad"
end
local function active_ai_scratchpad()
local file = io.open(ai_scratchpad_state_path(), "r")
if not file then
return ai_scratchpad_default
end
local value = file:read("*l")
file:close()
value = value and value:gsub("%s+", "")
if scratchpads[value] then
return value
end
return ai_scratchpad_default
end
local function toggle_active_ai_scratchpad()
toggle_scratchpad(active_ai_scratchpad())
end
-- Used by rofi_ai_scratchpad.sh after a selection: bring the chosen
-- scratchpad into view if it isn't already, without hiding it when it is.
local function show_active_ai_scratchpad()
local name = active_ai_scratchpad()
for _, window in ipairs(matching_scratchpad_windows(name)) do
if scratchpad_is_visible(window) then
return
end
end
toggle_scratchpad(name)
end
_G.im_hyprland_toggle_ai_scratchpad = toggle_active_ai_scratchpad
_G.im_hyprland_show_ai_scratchpad = show_active_ai_scratchpad
ctx.lower_contains = lower_contains
ctx.lower_contains_any = lower_contains_any
ctx.scratchpad_window_matches = scratchpad_window_matches
@@ -552,6 +600,9 @@ function M.setup(ctx)
ctx.refresh_shell_workarea_and_scratchpads = refresh_shell_workarea_and_scratchpads
ctx.adopt_matching_scratchpad_window = adopt_matching_scratchpad_window
ctx.toggle_scratchpad = toggle_scratchpad
ctx.active_ai_scratchpad = active_ai_scratchpad
ctx.toggle_active_ai_scratchpad = toggle_active_ai_scratchpad
ctx.show_active_ai_scratchpad = show_active_ai_scratchpad
end
return M

View File

@@ -0,0 +1,39 @@
#!/usr/bin/env zsh
set -euo pipefail
# Choose which AI app SUPER+ALT+C toggles as a scratchpad: Codex or Claude
# Desktop. The choice is written to a state file that the Hyprland Lua config
# reads at keypress time, so switching is dynamic and needs no reload.
state_file="${XDG_STATE_HOME:-$HOME/.local/state}/hypr/ai-scratchpad"
mkdir -p "${state_file:h}"
names=(codex claude)
labels=("Codex" "Claude Desktop")
current=codex
[[ -r "$state_file" ]] && current="$(<"$state_file")"
menu=""
for i in {1..${#names}}; do
marker=" "
[[ "${names[$i]}" == "$current" ]] && marker="● "
menu+="${marker}${labels[$i]}\n"
done
index="$(printf "$menu" | rofi -dmenu -i -p "AI scratchpad" -format i)" || exit 0
[[ -n "$index" ]] || exit 0
selected="${names[$((index + 1))]}"
[[ -n "$selected" ]] || exit 0
print -r -- "$selected" > "$state_file"
# Bring the freshly selected scratchpad into view (no-op if already visible).
if command -v hyprctl >/dev/null 2>&1; then
hyprctl -q eval "_G.im_hyprland_show_ai_scratchpad()" >/dev/null 2>&1 || true
fi
if command -v notify-send >/dev/null 2>&1; then
notify-send "AI scratchpad" "Super+Alt+C now toggles ${labels[$((index + 1))]}" || true
fi