Skip to content

Commit 12d6356

Browse files
committed
Init theme switcher
1 parent 3e29218 commit 12d6356

File tree

10 files changed

+273
-31
lines changed

10 files changed

+273
-31
lines changed

.config/kitty/kitty.conf

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Kitty config - Catppuccin Macchiato inspired
2+
include ~/.config/kitty/theme.conf
23
font_family JetBrainsMono Nerd Font
34
bold_font auto
45
italic_font auto
@@ -9,28 +10,7 @@ adjust_line_height 0
910
cursor_shape beam
1011
cursor_blink_interval 0
1112

12-
background #1e1e2e
13-
foreground #cdd6f4
14-
selection_background #585b70
15-
selection_foreground #cdd6f4
16-
cursor #f5e0dc
17-
18-
color0 #45475a
19-
color1 #f38ba8
20-
color2 #a6e3a1
21-
color3 #f9e2af
22-
color4 #89b4fa
23-
color5 #cba6f7
24-
color6 #94e2d5
25-
color7 #bac2de
26-
color8 #585b70
27-
color9 #f38ba8
28-
color10 #a6e3a1
29-
color11 #f9e2af
30-
color12 #89b4fa
31-
color13 #cba6f7
32-
color14 #94e2d5
33-
color15 #a6adc8
13+
3414

3515
window_padding_width 8
3616
tab_bar_edge top
@@ -62,4 +42,5 @@ map ctrl+shift+alt+l move_window right
6242
# Rename current tab
6343
map ctrl+shift+r set_tab_title
6444

65-
45+
allow_remote_control yes
46+
listen_on unix:/tmp/kitty

.config/kitty/theme-dark.conf

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Catppuccin Mocha (dark) - matches current kitty.conf colors
2+
3+
background #1e1e2e
4+
foreground #cdd6f4
5+
selection_background #585b70
6+
selection_foreground #cdd6f4
7+
cursor #f5e0dc
8+
9+
color0 #45475a
10+
color1 #f38ba8
11+
color2 #a6e3a1
12+
color3 #f9e2af
13+
color4 #89b4fa
14+
color5 #cba6f7
15+
color6 #94e2d5
16+
color7 #bac2de
17+
color8 #585b70
18+
color9 #f38ba8
19+
color10 #a6e3a1
20+
color11 #f9e2af
21+
color12 #89b4fa
22+
color13 #cba6f7
23+
color14 #94e2d5
24+
color15 #a6adc8
25+
26+

.config/kitty/theme-light.conf

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Catppuccin Latte (light) - complementary palette
2+
3+
background #eff1f5
4+
foreground #4c4f69
5+
selection_background #ccd0da
6+
selection_foreground #4c4f69
7+
cursor #dc8a78
8+
9+
color0 #5c5f77
10+
color1 #d20f39
11+
color2 #40a02b
12+
color3 #df8e1d
13+
color4 #1e66f5
14+
color5 #8839ef
15+
color6 #179299
16+
color7 #acb0be
17+
color8 #6c6f85
18+
color9 #d20f39
19+
color10 #40a02b
20+
color11 #df8e1d
21+
color12 #1e66f5
22+
color13 #8839ef
23+
color14 #179299
24+
color15 #bcc0cc
25+
26+

.config/kitty/theme.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/Users/george.leontiev/.config/kitty/theme-light.conf

.gitignore

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
# Local state
2+
.DS_Store
3+
4+
# Theme watcher artifacts
5+
.theme
6+
Library/Logs/theme-watcher.log
7+
8+
# User-host-only LaunchAgents should live under repo path launchd/, not in $HOME
9+
Library/LaunchAgents/local.theme-watcher.plist
10+
111
# Ignore everything by default
212
*
313

@@ -11,6 +21,10 @@
1121
!/scripts
1222
!/scripts/**
1323

24+
# Include launchd plists stored in the repo
25+
!/launchd
26+
!/launchd/**
27+
1428
# Root-level configs to keep
1529
!/.yabairc
1630
!/.skhdrc
@@ -27,6 +41,9 @@
2741
!/.config/sketchybar/**
2842
!/.config/kitty
2943
!/.config/kitty/kitty.conf
44+
!/.config/kitty/theme-light.conf
45+
!/.config/kitty/theme-dark.conf
46+
!/.config/kitty/theme.conf
3047
!/.config/starship.toml
3148
!/.config/nvim
3249
!/.config/nvim/**

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,15 @@ Kitty shortcuts:
7373

7474
### Neovim
7575

76+
### Auto Light/Dark theme
77+
78+
- A small LaunchAgent watches macOS appearance and runs `~/scripts/apply_theme.sh`.
79+
- The script writes the current mode to `~/.theme` and triggers a `sketchybar` `theme_change` event (falls back to `--reload`).
80+
- Kitty live-switching is supported if you provide:
81+
- `~/.config/kitty/theme-light.conf`
82+
- `~/.config/kitty/theme-dark.conf`
83+
- Add more actions by creating an executable `~/scripts/on_theme_change.sh` which will receive `light` or `dark` as its first arg.
84+
7685
- Config: `~/.config/nvim/init.lua` (lazy.nvim, LSP, Treesitter, Telescope, gitsigns, lualine, Catppuccin)
7786
- Common keys:
7887
- Space+ff: find files

install.sh

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,33 @@ link .ghci .ghci || true
9494

9595
link .config/sketchybar .config/sketchybar
9696
link .config/kitty/kitty.conf .config/kitty/kitty.conf
97+
link .config/kitty/theme-light.conf .config/kitty/theme-light.conf
98+
link .config/kitty/theme-dark.conf .config/kitty/theme-dark.conf
9799
link .config/starship.toml .config/starship.toml
98100
link .config/karabiner/karabiner.json .config/karabiner/karabiner.json || true
99101
link .config/nvim .config/nvim
100102

103+
# Theme watcher files
104+
link scripts/apply_theme.sh scripts/apply_theme.sh
105+
106+
# Install LaunchAgent plist (validated)
107+
install_launchd() {
108+
src="$THIS_DIR/launchd/local.theme-watcher.plist"
109+
dst="$HOME/Library/LaunchAgents/local.theme-watcher.plist"
110+
if [ "$DRY_RUN" -eq 1 ]; then
111+
echo "+ mkdir -p $(dirname "$dst")"
112+
echo "+ cp \"$src\" \"$dst\""
113+
echo "+ chmod 644 \"$dst\""
114+
echo "+ plutil -lint \"$dst\""
115+
else
116+
mkdir -p "$(dirname "$dst")"
117+
cp "$src" "$dst"
118+
chmod 644 "$dst" || true
119+
plutil -lint "$dst"
120+
fi
121+
}
122+
install_launchd
123+
101124
# 6) Start services
102125
title "Starting services"
103126
if command -v yabai >/dev/null 2>&1; then
@@ -128,6 +151,29 @@ if command -v sketchybar >/dev/null 2>&1; then
128151
fi
129152
fi
130153

154+
# 6b) Theme watcher (Light/Dark auto)
155+
title "Configuring theme watcher"
156+
if [ "$DRY_RUN" -eq 1 ]; then
157+
echo "+ chmod +x \"$HOME/scripts/apply_theme.sh\""
158+
echo "+ launchctl bootout gui/$(id -u) local.theme-watcher || true"
159+
echo "+ launchctl bootstrap gui/$(id -u) \"$HOME/Library/LaunchAgents/local.theme-watcher.plist\""
160+
echo "+ launchctl enable gui/$(id -u)/local.theme-watcher"
161+
echo "+ launchctl kickstart -k gui/$(id -u)/local.theme-watcher"
162+
echo "+ zsh -lc \"$HOME/scripts/apply_theme.sh\""
163+
else
164+
chmod +x "$HOME/scripts/apply_theme.sh" || true
165+
launchctl bootout gui/"$(id -u)" local.theme-watcher >/dev/null 2>&1 || true
166+
if ! launchctl bootstrap gui/"$(id -u)" "$HOME/Library/LaunchAgents/local.theme-watcher.plist"; then
167+
# Fallback for older macOS
168+
launchctl unload -wF "$HOME/Library/LaunchAgents/local.theme-watcher.plist" >/dev/null 2>&1 || true
169+
launchctl load -wF "$HOME/Library/LaunchAgents/local.theme-watcher.plist" || true
170+
else
171+
launchctl enable gui/"$(id -u)"/local.theme-watcher || true
172+
launchctl kickstart -k gui/"$(id -u)"/local.theme-watcher || true
173+
fi
174+
zsh -lc "$HOME/scripts/apply_theme.sh" || true
175+
fi
176+
131177
# 7) Post-install notes
132178
title "Post-install steps"
133179
cat <<'EOS'
@@ -139,6 +185,12 @@ cat <<'EOS'
139185
- Hide Menu Bar and Dock (System Settings) for a clean look
140186
- Set your terminal font to “JetBrainsMono Nerd Font”
141187
188+
- Automatic Light/Dark theme:
189+
- The theme watcher writes the current mode to ~/.theme and notifies apps
190+
- Kitty theme switching looks for:
191+
- ~/.config/kitty/theme-light.conf
192+
- ~/.config/kitty/theme-dark.conf
193+
142194
Tip: Kitty is installed. Launch with: open -na "Kitty" (or ⌥ + enter as configured by skhd)
143195
EOS
144196

launchd/local.theme-watcher.plist

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>Label</key>
6+
<string>local.theme-watcher</string>
7+
8+
<key>ProgramArguments</key>
9+
<array>
10+
<string>/bin/zsh</string>
11+
<string>-lc</string>
12+
<string>/Users/george.leontiev/scripts/apply_theme.sh</string>
13+
</array>
14+
15+
<key>RunAtLoad</key>
16+
<true/>
17+
18+
<key>StartInterval</key>
19+
<integer>1</integer>
20+
21+
<key>WatchPaths</key>
22+
<array>
23+
<string>/Users/george.leontiev/Library/Preferences/.GlobalPreferences.plist</string>
24+
</array>
25+
26+
<key>StandardOutPath</key>
27+
<string>/Users/george.leontiev/Library/Logs/theme-watcher.log</string>
28+
<key>StandardErrorPath</key>
29+
<string>/Users/george.leontiev/Library/Logs/theme-watcher.log</string>
30+
</dict>
31+
</plist>
32+
33+

scripts/apply_theme.sh

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
LOG_FILE="$HOME/Library/Logs/theme-watcher.log"
5+
mkdir -p "$(dirname "$LOG_FILE")"
6+
7+
timestamp() { date +"%Y-%m-%d %H:%M:%S"; }
8+
9+
is_dark() {
10+
# Prefer AppleScript for reliable detection on modern macOS
11+
if osascript -e 'tell application "System Events" to tell appearance preferences to get dark mode' \
12+
2>/dev/null | grep -qi true; then
13+
return 0
14+
fi
15+
# Fallback to defaults key
16+
defaults read -g AppleInterfaceStyle 2>/dev/null | grep -qi "Dark"
17+
}
18+
19+
# Allow overriding theme with first argument: 'light' or 'dark'
20+
THEME_OVERRIDE=${1:-}
21+
case "$THEME_OVERRIDE" in
22+
light|dark)
23+
THEME="$THEME_OVERRIDE"
24+
;;
25+
*)
26+
if is_dark; then
27+
THEME="dark"
28+
else
29+
THEME="light"
30+
fi
31+
;;
32+
esac
33+
34+
# Ensure PATH includes Homebrew bin for launchd context
35+
export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH"
36+
37+
# Determine kitty theme file paths
38+
KITTY_THEME_LIGHT="$HOME/.config/kitty/theme-light.conf"
39+
KITTY_THEME_DARK="$HOME/.config/kitty/theme-dark.conf"
40+
KITTY_THEME_LINK="$HOME/.config/kitty/theme.conf"
41+
42+
# Ensure the kitty startup include points to the current theme
43+
if [ "$THEME" = "dark" ] && [ -f "$KITTY_THEME_DARK" ]; then
44+
ln -sf "$KITTY_THEME_DARK" "$KITTY_THEME_LINK"
45+
elif [ "$THEME" = "light" ] && [ -f "$KITTY_THEME_LIGHT" ]; then
46+
ln -sf "$KITTY_THEME_LIGHT" "$KITTY_THEME_LINK"
47+
fi
48+
49+
PREV_THEME=""
50+
if [ -f "$HOME/.theme" ]; then
51+
PREV_THEME=$(cat "$HOME/.theme" 2>/dev/null || true)
52+
fi
53+
54+
if [ "$THEME" != "$PREV_THEME" ]; then
55+
echo "$(timestamp) Theme detected: $THEME" >>"$LOG_FILE"
56+
echo "$THEME" >"$HOME/.theme"
57+
fi
58+
59+
# Notify sketchybar if available
60+
if command -v sketchybar >/dev/null 2>&1; then
61+
if pgrep -x sketchybar >/dev/null 2>&1; then
62+
# Try to trigger a custom event first; fall back to reload
63+
sketchybar --trigger theme_change THEME="$THEME" >/dev/null 2>&1 || \
64+
sketchybar --reload >/dev/null 2>&1 || true
65+
fi
66+
fi
67+
68+
# Try to update kitty colors if remote control is available and theme files exist
69+
if command -v kitty >/dev/null 2>&1; then
70+
# Prefer fixed socket if configured to avoid controlling-terminal limitations
71+
if [ -S /tmp/kitty ]; then
72+
KITTYCTL=(kitty @ --to unix:/tmp/kitty)
73+
else
74+
KITTYCTL=(kitty @)
75+
fi
76+
# Apply to all running kitty windows regardless of change to enforce state
77+
if [ "$THEME" = "dark" ] && [ -f "$KITTY_THEME_DARK" ]; then
78+
"${KITTYCTL[@]}" set-colors --all --configured "$KITTY_THEME_DARK" >/dev/null 2>&1 || true
79+
elif [ "$THEME" = "light" ] && [ -f "$KITTY_THEME_LIGHT" ]; then
80+
"${KITTYCTL[@]}" set-colors --all --configured "$KITTY_THEME_LIGHT" >/dev/null 2>&1 || true
81+
fi
82+
fi
83+
84+
# Optional user hook for further customization
85+
if [ -x "$HOME/scripts/on_theme_change.sh" ]; then
86+
"$HOME/scripts/on_theme_change.sh" "$THEME" >>"$LOG_FILE" 2>&1 || true
87+
fi
88+
89+
exit 0
90+
91+

scripts/check.sh

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,26 @@ if ! have jq; then brew install jq; fi
1111
if ! have stylua; then brew install stylua; fi
1212

1313
echo '==> Shell lint'
14+
lint_files=( install.sh )
1415
if ls .config/sketchybar/scripts/*.sh >/dev/null 2>&1; then
15-
shellcheck -S error install.sh .config/sketchybar/scripts/*.sh
16-
else
17-
shellcheck -S error install.sh
16+
lint_files+=( .config/sketchybar/scripts/*.sh )
1817
fi
18+
if [ -f scripts/apply_theme.sh ]; then
19+
lint_files+=( scripts/apply_theme.sh )
20+
fi
21+
shellcheck -S error "${lint_files[@]}"
1922

2023
echo '==> Shell formatting check'
21-
files=( )
22-
[ -f install.sh ] && files+=( install.sh )
24+
fmt_files=( )
25+
[ -f install.sh ] && fmt_files+=( install.sh )
2326
if ls .config/sketchybar/scripts/*.sh >/dev/null 2>&1; then
24-
files+=( .config/sketchybar/scripts/*.sh )
27+
fmt_files+=( .config/sketchybar/scripts/*.sh )
28+
fi
29+
if [ -f scripts/apply_theme.sh ]; then
30+
fmt_files+=( scripts/apply_theme.sh )
2531
fi
26-
if [ ${#files[@]} -gt 0 ]; then
27-
shfmt -d -s -ci "${files[@]}"
32+
if [ ${#fmt_files[@]} -gt 0 ]; then
33+
shfmt -d -s -ci "${fmt_files[@]}"
2834
fi
2935

3036
echo '==> JSON validation (Karabiner)'

0 commit comments

Comments
 (0)