让 Kitty 和 Starship 跟着 KDE 一起换色
换壁纸取色、切配色方案、昼夜自动切换 —— 让终端配色自动跟上 KDE。两个零依赖 Python 脚本、一条 systemd 链路,以及一个会静默失败的竞态陷阱。
KDE 那边把 accent 调成了玫瑰粉,终端还停在上一套主题;Starship 的 git 分支胶囊又是另一个颜色。壁纸一换,三处全不对。
手动改当然可以,但每次换壁纸、每次切深浅色都要记得改一遍 —— 那就等于没改。
这篇讲的是一套自动方案:让终端配色跟着 KDE 走。读完你能得到两个零依赖的 Python 脚本、一条 systemd 自动同步链路,以及一个会静默失败的竞态陷阱的完整避坑方案。
配套代码与完整脚本:https://github.com/LaT-SKY/kde-terminal-theme-sync(MIT)
先决条件
| 需要 | 说明 |
|---|---|
| KDE Plasma 6 | 配色数据源。昼夜自动切换需要 6.5+ |
| Kitty | 终端本体,支持 `SIGUSR1` 热重载 |
| Starship | 提示符。`[palettes.*]` 需要 1.20+ |
| Python 3.8+ | 两个脚本只用标准库,没有 pip 依赖 |
| systemd –user | 自动同步用它。Arch / Fedora / Ubuntu 默认有 |
这套东西在什么环境上验证过
```plaintextCachyOS (Arch) | KDE Plasma 6 | Kitty | Starship 1.26.0 Wayland | Python 3.14
```
只在上面这一个组合上实测过。 下面这份清单说明哪些地方会因环境而异 —— 标 ✅ 的可以放心,标 ⚠️ 和 ❌ 的要自己确认一下:
- 配置文件路径(`
~/.config/…`)—— ✅ 通用。XDG 规范,各发行版一致。 - KDE 配色存储位置与优先级 —— ✅ 通用。同上。
- `
kdeglobals` 的内容 —— ⚠️ 因 Plasma 版本而异。见下面「一个会静默失败的陷阱」。 - Python —— ✅ 3.8+ 都行。只用标准库。
- `
systemd --user` —— ⚠️ 需发行版启用。`systemctl --user status` 自查。 - `
PathModified=` 的触发时机 —— ✅ 通用。systemd 行为。 - kitty 热重载 `
SIGUSR1` —— ✅ 通用。kitty 自身特性。 - starship 的 `
SIGWINCH` 重绘 —— ❌ 只对 fish 有效。bash / zsh 要换做法,见「第三步:让它自己跑起来」。 - 昼夜自动切换 —— ⚠️ 需要 Plasma 6.5+。低版本没有这个功能。
三个自查命令:
```bashpython3 --version # 要 3.8 以上 systemctl --user status # 能输出就说明有 systemd --user ls ~/.config/kdeglobals # 存在就说明有 KDE 配置
```
原理:KDE 把配色存在哪
搞清楚数据从哪来,后面所有事都好办了。KDE 的配色分散在三个地方,按优先级回退:
- `
~/.config/kdeglobals` —— 用户覆盖,优先级最高。accent 色这类个性化设置在这里 - `
~/.local/share/color-schemes/<名称>.colors` —— 用户自己装的配色 - `
/usr/share/color-schemes/<名称>.colors` —— 系统自带,最后兜底
当前用的是哪一套,从 `kdeglobals` 的 `[General] ColorScheme` 读。
⚠️ 一个反直觉的点
那个 `ColorScheme` 键不一定在 `kdeglobals` 里。
这不是配置写坏了。Plasma 在切换主题时是分阶段写文件的,而且写的地方不止一处 ——
方案名可能跑到了 `~/.config/kdedefaults/kdeglobals`。
自己确认一下:
```bash# 看 kdeglobals 里有没有 ColorScheme grep -n 'ColorScheme' ~/.config/kdeglobals # 如果没有,看这里 grep -n 'ColorScheme' ~/.config/kdedefaults/kdeglobals 2>/dev/null
```
记住这个细节 —— 「一个会静默失败的陷阱」的根因就在这儿。
`.colors` 基座文件是什么
`<名称>.colors` 是完整的配色方案文件,里面是 `[Colors:View]`、`[Colors:Window]`
这样的段。脚本读它的顺序是:
- 先读 `
kdeglobals` 里的 `[Colors:*]` 段(那是用户覆盖后的结果) - 再用 `
.colors` 文件补齐缺失的段
这个「补齐」在正常情况下是好事 —— 少几个键不影响。但它也正是那个陷阱 最难发现的地方,到时候会说。
第一步:读 KDE 配色,生成 Kitty 主题
先建一个目录放脚本。位置随意,但记住它 —— 后面 systemd 单元要指过来。
```bashmkdir -p ~/.local/share/kde-terminal-theme-sync cd ~/.local/share/kde-terminal-theme-sync
```
把 `generate-kitty-theme.py` 放进去。这个脚本 492 行,不铺在正文里 ——
下载或 clone 下来放到那个目录即可:
完整脚本:generate-kitty-theme.py 492 行 / 19.8 KB | 直接下载
下面讲它的两处设计决策。不用对着源码读,看完再回去翻也来得及。
先跑一次看看它能不能读出你的配色:
```bashpython3 generate-kitty-theme.py
```
我这边(BreezeDark)的输出是这样,这是真实运行结果:
```plaintext[*] 当前 KDE 配色方案: BreezeDark (来源: ~/.config/kdeglobals) [*] 读取基础配色文件: /usr/share/color-schemes/BreezeDark.colors [*] 检测到 暗色 主题 (背景亮度=22) foreground #fcfcfc background #151a1e cursor #3daee9
```
两个设计决策,值得单独讲
脚本里有两处看起来可以「更统一」、但故意不统一的地方。
① `background` 为什么要掺 5% accent
纯搬 KDE 的 `BackgroundNormal` 得到的是一块死板的灰。它和 KDE 窗口放在一起,
一眼能看出「不是一家人」。
所以脚本把 accent 按 5% 掺进背景 —— 上面那个 `#151a1e`,
原始 `BackgroundNormal` 是 `(20, 22, 24)`,掺入 accent 之后变成了 `#151a1e`。
差别很小,但整块背景「活」了。
② ANSI 蓝为什么不跟随 accent
这是更重要的一个。
如果你的 KDE `ForegroundLink` 被覆盖成了非蓝色(比如玫瑰粉),
`color4`(ANSI 蓝)不会跟着变 —— 脚本会检测色相,不是蓝就回退到标准蓝 `#2980b9`。
理由很实际:终端里太多程序用 ANSI 蓝表示「目录」「信息」「链接」。
它变成粉色之后,`ls` 的输出会读不懂 —— 目录和普通文件分不出来。
功能语义色不能为了好看让路。 这和「配色统一」是两回事, 脚本选了前者。
第二步:生成 Starship 调色板
同样放进那个目录(589 行,一样不铺在正文里):
完整脚本:generate-starship-palette.py 589 行 / 22.4 KB | 直接下载
为什么只改 `[palettes.kde]` 段
`starship.toml` 是你自己的配置文件,里面可能有大量手动调过的东西。
脚本默认整份输出(第一次用),但加上 `--palette-only` 就只更新
`[palettes.kde]` 这一段,其它原样保留:
```bashpython3 generate-starship-palette.py --palette-only
```
```plaintext[*] 首次备份到: ~/.config/starship.toml.bak [✓] palette 段已更新: ~/.config/starship.toml
```
自动同步链路用的就是 `--palette-only` —— 自动化不该覆盖你的手动配置。
调色板是怎么派生的
从 KDE 拿到的只有一个 accent 色。脚本用混色派生出三个层次:
| 键 | 怎么来的 | 用在哪 |
|---|---|---|
`accent` |
KDE `DecorationFocus` 原色 |
Git 分支胶囊(最醒目) |
`accent_soft` |
accent 与背景 55% 混合 | 主机名、用户名胶囊 |
`accent_dim` |
accent 与背景 25% 混合 | 目录、命令耗时胶囊 |
这样几个胶囊之间有层次,而不是一片同样的颜色。
第三步:让它自己跑起来
手动跑脚本能解决问题,但每次换壁纸都要记得跑一次,那就等于没有。
用 systemd 的用户级 Path 单元监听 `kdeglobals`。
下面这三个文件很短,直接铺开 —— 正文要讲解的部分必须能当场对着看:
```ini[Unit] Description=Watch kdeglobals for KDE theme changes [Path] # 监听这个文件被改写。KDE 换壁纸取色 / 切配色方案 / 昼夜自动切换 # 都会改写它,所以三种情况都能触发同步。 PathModified=%h/.config/kdeglobals [Install] WantedBy=default.target
```
```ini[Unit] Description=Sync Kitty/Starship colors from KDE theme After=graphical-session.target [Service] Type=oneshot # ⚠️ 路径按你的安装位置改。%h 是 systemd 的家目录占位符, # 所以这一份不用改就能用(前提是你把脚本放在这个目录)。 # 用 /usr/bin/bash 显式调用,省得依赖脚本的可执行位。 ExecStart=/usr/bin/bash "%h/.local/share/kde-terminal-theme-sync/auto-sync.sh"
```
同步入口:
```bash#!/usr/bin/env bash # KDE 配色变化 → 同步 Kitty/Starship(由 kde-theme-sync.path 触发,也可手动运行) # 幂等:内容无变化则不写盘、不发信号 # # 2026-09-19 竞态修复: # KDE 分阶段写 kdeglobals(先 General/ColorSchemeHash,颜色段随后落盘), # 而 systemd PathModified 在写入瞬间就触发,旧实现会读到半成品 → # 生成浅色主题 → 与已有文件逐字节相同 → 判定“无变化” → 永不重试, # 结果切到暗色模式后 kitty 背景仍是浅色(starship 因稍后读取而正常)。 # 现在:生成前等内容稳定,生成后复核,若期间又变则整体重跑;且生成器 # 遇到必需颜色缺失会退出码 3、本脚本跳过本次同步而不是写入浅色垃圾。 set -euo pipefail exec 9>/tmp/kde-theme-sync.lock flock -n 9 || exit 0 # 已有实例在跑则直接退出,防并发 # 脚本自己所在目录 —— **不写死路径**,clone 到哪都能跑。 # (原版写死了作者的私人路径,发布前必须去掉这类东西。) DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" KDEGLOBALS="$HOME/.config/kdeglobals" KITTY_CONF="$HOME/.config/kitty/colors-kde.conf" REDO_COUNT=0 # 本次同步内允许的“整体重跑”次数 MAX_REDO=2 SETTLE_WAIT=0.4 # 稳定采样间隔 SETTLE_TRIES=12 # 最多等 12×0.4s ≈ 4.8s # 内容摘要:作为“kdeglobals 是否仍在变”的判据 file_sig() { md5sum "$1" 2>/dev/null | cut -d' ' -f1; } # 等 kdeglobals 写完:连续两次采样摘要一致才继续(KDE 分阶段写盘) settle_kdeglobals() { local prev="" cur i for ((i = 0; i < SETTLE_TRIES; i++)); do cur="$(file_sig "$KDEGLOBALS")" [[ -n "$cur" && "$cur" == "$prev" ]] && return 0 prev="$cur" sleep "$SETTLE_WAIT" done echo "[$(date '+%F %T')] 警告:kdeglobals 在 $SETTLE_TRIES 次采样内未稳定,继续尝试" >&2 return 0 } # 返回 0 表示“内容在同步期间又变了,需要重跑”,1 表示稳定 kdeglobals_changed_since() { [[ "$(file_sig "$KDEGLOBALS")" != "$1" ]] } # ── 生成前:等 KDE 把 kdeglobals 写完 ── settle_kdeglobals while :; do SIG_BEFORE="$(file_sig "$KDEGLOBALS")" TMP_K="$(mktemp)" if ! python3 "$DIR/generate-kitty-theme.py" -o "$TMP_K"; then # 退出码 3 = kdeglobals 半成品(生成器已自行重试过);其余为真实错误 echo "[$(date '+%F %T')] kitty 配色生成失败(kdeglobals 尚未写完或数据异常),本次跳过" >&2 rm -f "$TMP_K" exit 0 fi # 1) Kitty:生成到临时文件比对,仅内容变化时落盘并 SIGUSR1 热重载 if ! cmp -s "$TMP_K" "$KITTY_CONF"; then cp "$TMP_K" "$KITTY_CONF" pkill -USR1 -x kitty 2>/dev/null || true echo "[$(date '+%F %T')] kitty colors-kde.conf 已更新并发送 SIGUSR1" else echo "[$(date '+%F %T')] kitty 配色无变化" fi rm -f "$TMP_K" # 2) Starship:只更新 [palettes.kde] 段(脚本内部自带幂等) OUT="$(python3 "$DIR/generate-starship-palette.py" --palette-only 2>&1 || true)" if echo "$OUT" | grep -q "palette 段已更新"; then # 真正写入了新 palette → 通知所有 fish 重绘 prompt(等效窗口 resize; # SIGWINCH 默认忽略、无杀伤。fish 重绘时 starship 重读配置即换色, # 解决 transience 下已开终端 prompt 不刷新问题) pkill -WINCH -x fish 2>/dev/null || true echo "[$(date '+%F %T')] starship palette 已更新,已通知 fish 重绘" elif echo "$OUT" | grep -q "palette 无变化"; then echo "[$(date '+%F %T')] starship palette 无变化" else echo "[$(date '+%F %T')] starship 更新异常:$OUT" >&2 fi # ── 生成后复核:若 kdeglobals 在本次同步期间又被改写(说明读到的可能仍是半成品),整体重跑 ── if kdeglobals_changed_since "$SIG_BEFORE"; then if ((REDO_COUNT < MAX_REDO)); then REDO_COUNT=$((REDO_COUNT + 1)) echo "[$(date '+%F %T')] 检测到 kdeglobals 在同步期间再次变化,重跑同步(第 $REDO_COUNT 次)" settle_kdeglobals continue fi echo "[$(date '+%F %T')] 警告:kdeglobals 在 $MAX_REDO 次重跑后仍在变化,放弃本次同步" >&2 fi break done
```
整条链路是这样:
```plaintextkdeglobals 变化 └─ kde-theme-sync.path │ (systemd --user,监听文件修改) └─ kde-theme-sync.service oneshot └─ auto-sync.sh ├─ 生成到临时文件 ├─ 与现有配置逐字节比对 ├─ 有变化才落盘 ├─ kitty: SIGUSR1 热重载 └─ starship: 只更新 [palettes.kde] 段
```
这张图刻意每行不超过 44 列 —— 手机上不用横向滚动就能一眼看全。 代码块本身是支持横向滚动的(超宽时在块内滑动,页面不动), 但对树形图来说,能一眼看全比能滚动有用。
为什么用 `PathModified=` 而不是定时轮询
KDE 改配置是事件驱动的。轮询要么延迟高(间隔大),要么空转(间隔小)。
`PathModified=` 精确到「这个文件被写了」这个事件。
热重载:两个信号,各有各的原因
Kitty —— `SIGUSR1`。 Kitty 收到就重新读配置文件。没有它,你得重启终端。
Starship —— `SIGWINCH`。 这个稍微绕一点:
Starship 每次画 prompt 都会重读配置,所以新开的终端本来就会用新色。 但已经开着的终端不会 —— 它会一直停在旧色上。
`SIGWINCH` 是终端窗口大小改变的信号。fish 收到会重绘 prompt,
重绘时 Starship 重新读配置,于是已开终端也即时换色。
```bashpkill -WINCH -x fish 2>/dev/null || true
```
⚠️ 注意 `
-x`:它要求进程名精确匹配。不要用 `pkill -f` —— 那个模式串会匹配到命令行里任何含该字符串的进程,包括执行它的那个 shell 自己。
不用 fish 怎么办
上面那一行是唯一和 shell 绑定的地方。换 shell 就换它:
- fish —— `
pkill -WINCH -x fish`(本方案默认) - bash —— `
pkill -WINCH -x bash`。但 bash 收到 `SIGWINCH` 不一定重绘 prompt,可能仍需新开终端 - zsh —— 同理;可以用 `
TRAPWINCH` + `zle reset-prompt`,但需要额外配置
其它部分与 shell 无关。 你也可以直接删掉那一行 —— 代价只是已开终端要新开一个才换色。
安装
```bash# 1. 装 systemd 单元 cp kde-theme-sync.path kde-theme-sync.service ~/.config/systemd/user/ systemctl --user daemon-reload systemctl --user enable --now kde-theme-sync.path # 2. Kitty 那边接上 include(~/.config/kitty/kitty.conf) # include colors-kde.conf # 3. 看状态 systemctl --user status kde-theme-sync.path journalctl --user -u kde-theme-sync.service -f
```
`.service` 里默认写的是 `%h/.local/share/kde-terminal-theme-sync/auto-sync.sh`
(`%h` 是 systemd 的家目录占位符)。脚本放在别处就改那一行。
⚠️ 一个会静默失败的陷阱
这一节是全文最值钱的部分。 任何监听 KDE 配置文件的工具都可能踩进去, 而且它失败的时候日志里一切正常。
现象
自动同步上线两周后,某天切到暗色模式:
kitty 背景仍是浅色,而 starship 已经正确变暗。
同一个桌面、同一次切换、同一份输入,一个跟上了,一个没跟上。
journal 里更奇怪:
```plaintext9月 19 18:30:16 Starting Sync colors... 9月 19 18:30:16 kitty 配色无变化 ↑ 该更新却判定"无变化" 9月 19 18:30:16 starship palette 已更新 ↑ 同一份输入却变了
```
同一秒、同一份 `kdeglobals`,两个脚本得出相反结论。
根因链
六步,一步都不能少。
- KDE 写 `
kdeglobals` 是分阶段的。 不是一次写完 —— 可能先落 `[General]`,颜色段随后才写 - `
PathModified=` 在第一次写入事件就触发。 它不知道「文件还没写完」这回事 - 同步抢在颜色段落盘之前读文件。 读到的是「有 `
[General]`、无 `[Colors:View]`」的中间态 - 取色函数拿不到值,回退到默认。 于是生成一份看起来正确的浅色主题
- 它与磁盘上已有的浅色文件逐字节相同 → 幂等比对判定「无变化」→ 不写盘、不发信号
- 颜色段真正落盘时,`
PathModified` 不再触发(文件已经“改过”了)→ 永远不重试 → kitty 永久僵在浅色
而 starship 那个脚本晚了一点点拿到完整文件,所以它变暗了。
结论:这是同步链路的竞态 ——「读到半成品 + 只比较一次」,不在 kitty,也不在 starship。
为什么它特别隐蔽
三个「看起来正常」叠在一起:
- 脚本没报错(它确实成功生成了一个主题)
- 日志说**「配色无变化」**(从它的角度看,确实没变化)
- 终端里确实有一个配色(只是错的)
没有任何一个环节会亮红灯。 你只会觉得「这次怎么没跟上」, 手动跑一次又好了 —— 于是永远查不到根因。
三条防线
一、生成前等它写完。 不抢跑,连续两次采样内容一致才继续:
```bashsettle_kdeglobals() { local f="$HOME/.config/kdeglobals" prev="" cur i for ((i = 0; i < 12; i++)); do cur="$(md5sum "$f" | cut -d' ' -f1)" [[ "$cur" == "$prev" ]] && return 0 prev="$cur"; sleep 0.4 done return 0 # 超时也继续,避免卡死整条链路 }
```
二、只接受完整输入。 `[Colors:View] BackgroundNormal` 缺失就视为
「还没写完」,报错退出(退出码 3),让调用方跳过本次 ——
而不是拿默认值生成一份浅色垃圾。
三、生成后复核。 再校验一次摘要;如果期间又变了(说明 KDE 还在写), 整体重跑,上限 2 次。
三层叠起来的效果一句话:
宁可这次不更新,也绝不写入错误的颜色。 不更新只是晚一点,写错了会一直错到下次切换。
退出码约定
调用方要据此决策,所以写进文档:
- 0 —— 成功(含「无变化」),正常。
- 2 —— 参数错误,修正调用。
- 3 —— KDE 配色数据不完整(半成品,重试后仍缺关键段)。`
auto-sync.sh` 跳过本次,等下次变化再触发。
调试重试节奏用 `--wait <秒>` / `--attempts <次数>`;
需要退回旧行为(缺失时用回退默认值)时加 `--allow-missing-colors` ——
但那个开关只该用来排错,不该进自动化链路。
⭐ 「浅色垃圾」到底是什么颜色
这里有个连我自己第一版都复现错的地方,值得讲清楚。
拿一个半成品 `kdeglobals`(只剩 `[General]`)配合 `--allow-missing-colors` 跑:
- `
[General] ColorScheme=BreezeDark`(方案名还在)- 新行为:退出码 3,不写盘 ✅
- 旧行为:⚠️ 仍然正确 —— 方案名还在,从 `
.colors` 兜底读到了
- 只剩 `
ColorSchemeHash`(方案名也不在)- 新行为:退出码 3,不写盘 ✅
- 旧行为:❌ 产出 `
background #f5fafd`(近白)
关键在第二条。 只有方案名也缺失时,兜底路径才断掉,
取色函数才会拿到默认值 `(255,255,255)` → 判为亮色 → 生成近白的浅色。
而那个近白的浅色,恰好与磁盘上已有的浅色文件逐字节相同 —— 于是触发第 5 步的「无变化」判定,永远不再重试。
这也解释了为什么这个问题那么难查:它需要两个条件同时成立 (颜色段缺失 + 方案名缺失)才会发生。偶发、难复现、日志正常。
第二个坑:判断「完整性」必须看原始文件
第一版我把「必需颜色是否齐全」的判断放在合并后的字典上。测试直接打脸:
`.colors` 基座文件会把缺失的 `[Colors:View]` 补齐 —— 防护形同虚设,
真实缺色的 `kdeglobals` 照样生成了浅色主题。
必须判断原始的 `kdeglobals`。 因为「半成品」的定义就是
原始文件里颜色段还没落盘,跟合并后的结果没关系。
怎么验证它真的在工作
隔离测试:用假 `HOME`,不碰真实配置
不要去动你自己的 `~/.config/kdeglobals`。造一个假的:
```bashFAKE=/tmp/fakehome mkdir -p $FAKE/.config # 用系统自带的 BreezeDark 造一份"完整"的 kdeglobals { echo '[General]' echo 'ColorScheme=BreezeDark' echo 'ColorSchemeHash=deadbeef' echo # 把系统配色文件里的 [Colors:*] 段搬进来 awk '/^\[Colors:/{p=1} /^\[(?!Colors:)/{p=0} p' \ /usr/share/color-schemes/BreezeDark.colors } > $FAKE/.config/kdeglobals
```
然后 `HOME=$FAKE python3 generate-kitty-theme.py` —— 输出与真实环境一致。
手动复现那个陷阱
这是最值得跑一遍的测试。
```bash# ① 只写 [General],模拟"KDE 还在写"的中间态 printf '[General]\nColorSchemeHash=deadbeef\n' > $FAKE/.config/kdeglobals # ② 跑一次 —— 应当退出码 3、一个字节都不写 HOME=$FAKE python3 generate-kitty-theme.py --wait 0.3 --attempts 2 echo "退出码: $?"
```
真实的输出:
```plaintext[!] kdeglobals 尚未写完(缺 kdeglobals[Colors:View]/BackgroundNormal),0.3s 后重试 (2/2) [✗] KDE 配色数据不完整,缺少: kdeglobals[Colors:View]/BackgroundNormal。 通常是 kdeglobals 正在被写入的半成品状态。 本次跳过,不更新 Kitty 配色。
```
```plaintext退出码: 3 ← stdout 零行,什么都没写
```
再试「写到一半又补上」 —— 也就是当初 bug 的原始场景:
```bash# 先写半成品,1.2 秒后在后台补全 printf '[General]\nColorSchemeHash=deadbeef\n' > $FAKE/.config/kdeglobals ( sleep 1.2; cp /tmp/full-kdeglobals $FAKE/.config/kdeglobals ) & HOME=$FAKE python3 generate-kitty-theme.py --wait 0.4 --attempts 6
```
```plaintext[!] kdeglobals 尚未写完(缺 kdeglobals[Colors:View]/BackgroundNormal),0.4s 后重试 (2/6) [!] kdeglobals 尚未写完(缺 kdeglobals[Colors:View]/BackgroundNormal),0.4s 后重试 (3/6) [!] kdeglobals 尚未写完(缺 kdeglobals[Colors:View]/BackgroundNormal),0.4s 后重试 (4/6) [*] 当前 KDE 配色方案: BreezeDark (来源: ~/.config/kdeglobals) [*] 检测到 暗色 主题 (背景亮度=22)
```
```plaintext退出码: 0 ← 重试机制接住了,拿到正确的暗色
```
旧代码在这个场景下必然留下浅色。 现在它会重试到数据完整为止。
排错
- 完全不生效
- `
kde-theme-sync.path` 没启用 → `systemctl --user status kde-theme-sync.path` - systemd 单元里的路径不对 → 看 `
.service` 的 `ExecStart`,路径要与脚本实际位置一致 - Kitty 没接上 → `
~/.config/kitty/kitty.conf` 里要有 `include colors-kde.conf`
- `
- 换了颜色但已开终端不变
- Starship 需要重绘 → 那一行 `
SIGWINCH` 是否生效?新开一个终端验证是否正常 - 不是 fish → 见上面「不用 fish 怎么办」
- Starship 需要重绘 → 那一行 `
- 亮暗切换时 kitty 不跟随 —— 就是那个竞态。确认脚本版本包含三条防线;手动跑一次 `
bash auto-sync.sh` - 脚本报退出码 3 —— `
kdeglobals` 是半成品。正常防护,等下次变化;反复出现就加大 `--wait` / `--attempts` - 颜色明显不对 —— 方案名读错了。`
grep ColorScheme ~/.config/kdeglobals ~/.config/kdedefaults/kdeglobals` - ANSI 蓝没跟着 accent 变 —— 这是故意的。功能语义色不跟随,见「第一步」里「ANSI 蓝为什么不跟随 accent」
备选方案:kitty 自带的 `auto-color-scheme`
Kitty 0.38 起自带这个功能:跑一次 `kitten themes`,把主题分别存成
light / dark / no-preference 三份 `*.auto.conf`,之后 kitty 自己查询系统配色并切换。
不需要任何外部脚本。 听起来应该直接换过去,但它有个要命的性质:
When these files exist, the colors in these files override all other colors, and also all background image settings, even those specified using the `
kitty --override` command line flag.
它会完全压制 `include colors-kde.conf`。也就是说,用了它就等于放弃跟随
KDE 的 accent 和壁纸取色 —— 而那正是这套东西存在的理由。
什么时候它更合适:你只需要亮/暗跟随,不需要终端配色「从壁纸长出来」。
文件清单
- `
generate-kitty-theme.py` - 读 KDE 配色 → 生成 Kitty 主题。放在 `
~/.local/share/kde-terminal-theme-sync/`。 - `
generate-starship-palette.py` - 读 KDE 配色 → 生成 Starship 调色板。同上。
- `
auto-sync.sh` - 同步入口:幂等比对 + 热重载信号。同上。
- `
kde-theme-sync.path` - 监听 `
kdeglobals`。放在 `~/.config/systemd/user/`。 - `
kde-theme-sync.service` - oneshot 执行 `
auto-sync.sh`。同上。
完整代码:https://github.com/LaT-SKY/kde-terminal-theme-sync(MIT,可直接 clone)
```bashgit clone https://github.com/LaT-SKY/kde-terminal-theme-sync
```
参考
- kitty 配置文档:`
/usr/share/doc/kitty/html/` - kitten-themes(1) man page
- kitty 官方文档 themes.rst