Saving a theme stopped sticking: the choice was captured only by the fish
`kitten` wrapper, so `kitty +kitten themes`, a keybinding or any non-fish
shell wrote <appearance>-theme.auto.conf directly and the next regeneration
overwrote it from theme-modes. The dark slot had already lost a pick that
way -- dark-theme.auto.conf held #0d0f31 while canonical dark said #2b2c2e.
Move the capture into apply-theme-mode.sh, which every path runs. It records
a cksum of each generated file after the repair step; on the next run a file
whose checksum differs was written by something else, so it becomes canonical
for that appearance. With no state recorded yet nothing is adopted, so a
first run cannot mistake a pinned mode's duplicated files for real choices.
The fish wrapper keeps only its useful part: re-apply the mode and reload so
the change shows at once.
theme-modes/dark.conf is the recovered #0d0f31 (1984). Covered by a new case
in tests/test_theme_mode.sh that writes the theme file with no shell involved.
The ping wrapper only asked whether the *target* had an AAAA record, never
whether this machine could reach over IPv6, so `ping ya.ru` ran ping6 and
died with "No route to host" while IPv4 worked fine.
Checking for a default v6 route is not sufficient either: this Mac has one
while holding only ::1 and fe80:: link-locals. So require a global unicast
address (2000::/3) as well as the route, which is the condition that
actually fails here.
ping4 is now platform-split rather than branching internally, since macOS
ping rejects -4:
macOS ~/.local/bin/ping (wrapper) and ~/.local/bin/ping4 -> /sbin/ping
Linux a fish function running `ping -4`
.chezmoiignore gates each side so neither lands where it cannot work.
`kitten themes` treats every .conf in <config-dir>/themes as a user
theme, which the mode system's canonical store was sitting in -- so the
picker was offering three bogus entries named light, dark and
no-preference, and had been since that store was introduced.
Move the store to ./theme-modes so ./themes means only what the kitten
means by it, and repoint apply-theme-mode.sh, the kitten shim, the
run_after hook and the test at the new path.
GrokNight and GrokDay move into ./themes with the ## name/author/
license/upstream/blurb header the kitten reads, so they now show up in
`kitten themes` and `--dump-theme` resolves them.
theme-modes/dark.conf carries the #202020 theme that was already on
disk: the file had to be re-added at its new path, so that drift comes
along with it.
kitty gives *-theme.auto.conf priority over everything -- includes and
even --override -- and has no option to stop following the OS. So the
only way to start in a chosen mode is to control what those files
contain. Make them generated:
themes/{light,dark,no-preference}.conf canonical, the real themes
theme-mode auto | light | dark
apply-theme-mode.sh writes the three .auto.conf
Under `auto` each appearance keeps its own theme, so kitty follows the
OS as before. Pinned, all three get the pinned theme, so kitty starts in
it whatever the OS says and a config reload no longer resets it.
`theme` now records the mode and reloads instead of calling set-colors,
which is why the setting survives restarts. A bare `theme` records
`auto` rather than pinning when the toggle lands on the macOS
appearance, so nothing is pinned unless it actually differs.
The kitten shim hashes the automatic theme files before running `kitten
themes` and copies whichever changed into themes/, so picking a new
light theme while pinned to dark is kept and applied on the next switch.
Covered by tests/test_theme_mode.sh.
conf.d/kitty_theme.fish is gone: theme-mode is now the source of truth,
so the universal-variable tracker it maintained is redundant.
__kitty_tab_set sent a luminance-picked black/white active_fg, so a
tinted tab's title looked different from a normal one. Send NONE
instead: tab_fg() then falls back to the shared active foreground (the
theme background) while active_bg keeps the per-host tint.
Covered by a new case in tests/test_tab_bar_colors.py matching what
__kitty_tab_set actually sends — host background, no fg override.
The bare command substitution ran on every shell start regardless of
platform, so Linux/WSL printed "fish: Unknown command: security" at
login — the 2>/dev/null only redirects the command's own stderr, not
fish's command-not-found diagnostic.
Guard with `type -q security`, matching conf.d/codex-github-mcp.fish,
and skip the export when the lookup returns nothing so a missing
keychain item no longer exports an empty GITHUB_PERSONAL_ACCESS_TOKEN.
`theme` switches kitty between the existing dark-theme.auto.conf and
light-theme.auto.conf via `kitty @ set-colors --all --configured`, so it
stays in sync with whatever `kitten themes --light/--dark` selects.
Subcommands: light, dark, auto (hand control back to the OS appearance
via load-config), status.
Tide is resynced by calling __tide_apply_terminal_appearance directly,
so the prompt recolors even if kitty sends no palette-change
notification for a dynamic color change. conf.d/kitty_theme.fish tracks
$fish_terminal_color_theme into $kitty_theme_mode so the toggle still
reads the real state after kitty follows an OS appearance change.
light-theme.auto.conf had no tab colors, which left the dark tab bar on
a light background after switching; add a matching tab style block.
Tint the kitty tab background by target host so local vs remote (and
which remote) is visible at a glance.
- __kitty_host_color: explicit color table for known hosts (routers,
resolvers, ryzen/mini, personal cloud, geo VPS) + stable hashed
palette fallback; auto-picks readable fg by luminance
- __kitty_ssh_host: parse target host from ssh/mosh-style argv
- __kitty_tab_set/__kitty_tab_reset: active tab = full host-color bg,
inactive tab = dark theme bg with host-color text; revert on exit
- ssh wrapper + s (kitten ssh) and m (mosh) wired to tint/reset
Also includes unrelated pending dotfile changes (GH MCP PAT from
keychain in fish/zsh, kitty/wezterm font_size 15->14, kitty
colorspace displayp3) committed together at user request.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Extract tide configuration into a reusable fish function (tide-reset)
and call it from the chezmoi onchange script. Also revert treesitter
config to the stable API (nvim-treesitter.configs).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Kitty doesn't set TERM_PROGRAM, check TERM=xterm-kitty instead.
Also use modern `kitten ssh` command.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use antonme/tide fork (from plttn/tide v7) which includes fix for
bold leaking from home directory pwd rendering
- Replace fragile index-based tide_right_prompt_items removal with
explicit name-based filtering of node, gcloud, and kubectl
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>