mattj85/SpookiUI
GitHub: mattj85/SpookiUI
SpookiUI 是一个用 Python 标准库编写的 Ghostty 终端实时配置 TUI 工具,解决了 Ghostty 无法自动热重载配置文件的问题。
Stars: 75 | Forks: 3
# SpookiUI
一个用于 **[Ghostty](https://ghostty.org) 终端的实时配置工具**。浏览
并编辑 Ghostty 支持的*每一个*选项,通过交互式终端 UI 进行操作,并
实时查看您的更改应用情况 —— 当您在 Ghostty 窗口中运行它时,您所在的
终端会在您编辑时实时重绘。

```
./spookiui.py
```
需要 Python 3.8+(仅使用标准库 —— 无需 pip 安装)以及
位于您的 `PATH`(或 `/Applications/Ghostty.app`)中的 `ghostty` 二进制文件。
## 安装说明
SpookiUI **没有第三方 Python 依赖** —— 它是一个单脚本,
运行在 Python 3.8+ 标准库上。您可以直接从代码库运行它:
```
git clone https://github.com/mattj85/SpookiUI.git
cd SpookiUI
./spookiui.py
```
或者运行安装程序(macOS 和 Linux)来检查前置条件,并将 `spookiui`
命令放到您的 `PATH` 中:
```
./install.sh # installs to ~/.local/bin
PREFIX=/usr/local ./install.sh # system-wide (may need sudo)
```
安装程序会验证 Python 3.8+,检查 `ghostty` 二进制文件(如果缺失,会发出警告
并提供安装提示),并将 `spookiui.py` 符号链接到您的 bin
目录中。运行后,`spookiui` 和 `spookiui --help` 就可以在任何地方使用了。
要撤销安装,请运行卸载程序(传入您安装时使用的相同 `PREFIX`):
```
./uninstall.sh # remove the `spookiui` command
PREFIX=/usr/local ./uninstall.sh # if you installed there
./uninstall.sh --purge # also delete SpookiUI's cache + saved profiles
```
它只会删除它识别为由自身创建的符号链接(绝不会删除它未创建的文件,
也绝不会删除通过 Homebrew 安装的版本 —— 请使用 `brew uninstall` 来卸载),并且
保留您的 Ghostty 配置和代码库不变。
### Homebrew (macOS 和 Linux)
Homebrew formula 位于 [`homebrew/spookiui.rb`](homebrew/spookiui.rb) 中。一旦
它被发布到名为 `homebrew-spookiui` 的 tap 仓库中,就可以使用以下命令安装:
```
brew install mattj85/spookiui/spookiui
```
Homebrew 安装可通过 `brew upgrade spookiui` 进行更新;应用内的更新器
会检测到 Homebrew 安装并将更新操作交由其处理。
## 为什么会有这个工具
Ghostty 通过纯文本文件(`~/.config/ghostty/config`)进行配置,并且
**无法在文件更改时自动重新加载** —— 您必须自行触发重新加载。
SpookiUI 闭合了这个循环:它不仅写入配置文件,还会为您触发 Ghostty
重新加载 —— 在 macOS 上点击 **Reload Configuration** 菜单项,或者在 Linux 下
向正在运行的进程发送它用于重新加载的 **SIGUSR2** 信号 ——
这样编辑感觉就像是实时的。它可以在 macOS 和 Linux 上运行。
每个选项都是从您安装的 Ghostty 中**动态发现**的
(`ghostty +show-config --default --docs`),因此该工具始终与您的
版本匹配 —— 没有任何内容是硬编码的。在这台机器上,这涵盖了 13 个
类别中的约 200 个选项。仅适用于*其他*操作系统(在 Linux 上的仅 macOS
设置,或在 macOS 上的 GTK/X11 设置)的选项会被**自动隐藏**,因此您
只能看到与您当前机器相关的内容。
## 实时循环
```
you edit a value ─▶ SpookiUI writes the config file
│
├─▶ validates it with `ghostty +validate-config`
│ (an invalid value is rejected & rolled back)
│
└─▶ reloads Ghostty ─▶ your terminal repaints
(macOS: "Reload Configuration" menu item via
AppleScript · Linux: SIGUSR2 to the process)
```
- **安全:** 每次更改在保存之前都会由 Ghostty 本身进行验证。错误的
值永远不会进入您的配置。
- **可撤销:** 在每天第一次更改时会生成一个带日期的备份(`config.spookiui.YYYYMMDD.bak`),TUI 可以通过 `R` 恢复整个会话,并且您
可以使用 `X` 将配置恢复为 Ghostty 的内置默认值(仍会保留备份)。
- **实时预览:** 在选择主题、字体或枚举值时,每个高亮显示的
选项都会在您滚动时应用 —— 取消选择,它会立即恢复到原来的状态。
## 各平台的实时重载
Ghostty 无法监视其配置文件的更改,因此 SpookiUI 会为您触发重载。
具体如何触发 —— 以及需要什么条件 —— 取决于您的操作系统:
| 平台 | 如何触发重载 | 要求 |
| --- | --- | --- |
| **macOS** | 通过 AppleScript (`osascript`) 点击 **Reload Configuration** 菜单项 | Ghostty 必须正在运行;您的终端需要 **辅助功能 (Accessibility)** 权限(*系统设置 → 隐私与安全性 → 辅助功能*)。Ghostty 位于 `PATH` 或 `/Applications/Ghostty.app` 中。 |
| **Linux** | 向正在运行的 Ghostty 进程发送 **`SIGUSR2`** 信号,Ghostty 会据此重载 | Ghostty 必须正在运行;使用 `pgrep`(来自 `procps`/`procps-ng`,几乎所有发行版都有)来查找它。无需额外权限。适用于任何发行版 —— 检测是通用的(`sys.platform`),没有特定于发行版的代码。 |
| **其他** | *无自动重载* —— 文件仍会被写入并验证 | 在 Ghostty 中触发您自己的 `reload_config` 快捷键来应用。 |
在 **Linux** 上,Ghostty 通过 `PATH` (`shutil.which`) 查找,如果找不到则回退至
`/usr/bin/ghostty` 和 `/usr/local/bin/ghostty`。仅需要 Python 3.8+(标准
库)和 `ghostty` 二进制文件;实时重载还需要
`pgrep` 和一个正在运行的 Ghostty 实例。
如果无法触发重载(Ghostty 未运行、缺少权限或
是不支持的平台),您的更改**仍会被安全地写入并验证** ——
SpookiUI 只会提示您手动重载。少数选项(例如 `language`)完全
无法在不重启的情况下应用;UI 会将这些标记为*需要重启* /
*仅限新窗口*,以免造成意外。
## TUI
```
SpookiUI · live Ghostty configurator AUTO-APPLY:ON · live
Colors & Theme │ ● theme Catppuccin Mocha │ theme
Font │ background #1e1e2e │ type: theme
Cursor │ foreground #cdd6f4 │ value: Catppuccin…
Window │ ● background-opacity 0.95 │ ─ docs ───────────
… │ … │ Set the color …
```
| 按键 | 操作 |
| --- | --- |
| `↑`/`↓` 或 `j`/`k` | 移动 · `Tab` 切换面板 |
| `→`/`Enter` | 进入选项 / **编辑**选中的选项 |
| `←` | 返回类别 |
| `/` | 按名称或文档搜索所有选项 |
| `u` | 将选中的选项重置为默认值 |
| `a` | 切换**自动应用**(实时 ↔ 暂存) |
| `s` | 保存 + 立即重载 · `r` 重新触发重载 |
| `R` | 将所有内容恢复到会话开始时的状态 |
| `X` | 清除配置并恢复**所有** Ghostty 默认值(保留备份) |
| `U` | 就地将 SpookiUI 更新到最新版本 |
| `p` | **配置文件** —— 保存 / 加载 / 删除已命名的配置 · `t` 切换浅色↔深色 |
| `c` | **配置检查** (doctor) —— 健康检查以发现问题 |
| `v` | **实用工具** —— 一次性修复(例如 **修复 SSH**) |
| `d` | 显示您已更改的所有内容 |
| `?` | 帮助 · `q` 退出 |
当您的终端字体是 **Nerd Font** 时,左列中的每个类别
都会获得一个图标(调色板、字体、光标、apple/linux 等)。SpookiUI 会从
Ghostty 的 `font-family` 中检测到这一点;如果没有设置 Nerd Font,它会显示一次性提示,说明如何为您的平台安装 Nerd Font,然后
在没有图标的情况下运行。可以使用 `SPOOKIUI_ICONS=1` / `SPOOKIUI_ICONS=0` 强制开启或关闭。
编辑器根据每个选项的类型而定:
- **布尔值** 瞬间切换
- **枚举 / 字体** 打开一个带有实时预览的可搜索选择器,列出 Ghostty 文档中的*每一个*
有效选择(例如所有 11 种 `macos-icon` 样式)
- **主题** 打开带有高亮显示主题的**实时颜色卡片**的选择器 —— 其 16 色调色板和背景上的前景色样本,就渲染
在列表旁边,让您在应用前就能看到主题效果
- **有界数字**(不透明度、`minimum-contrast` 等)打开一个**可视滑块** ——
`←`/`→` 进行微调,`PgUp`/`PgDn` 进行大幅度调整,`Home`/`End` 调整到两端,
所有操作均实时预览
- **其他数字** 使用 `↑`/`↓` 或 `+`/`-` 逐步调整,或直接输入值
- **颜色 / 文本** 接受输入的值(`#rrggbb` 或命名的颜色);颜色会显示
色板,颜色选项会在详细信息面板中预览当前活动的调色板
- **快捷键** 打开一个**向导构建器** —— 切换修饰键(`super`/`ctrl`/
`alt`/`shift`,在 macOS 上 `super` 即 ⌘),按下或选择按键,并从
Ghostty 自己的操作列表中选择操作;结果在添加之前会进行验证
- **其他列表**(`palette`、`env`、字体回退等)获得一个添加/编辑/删除
编辑器
**关闭自动应用** 会将您的编辑暂存在内存中,而不会触及磁盘;按下
`s` 可一次性写入并重载它们。
在 macOS 上,您还可以从这里重新设置**应用图标**样式:选择一种 `macos-icon`
样式(`official`、`blueprint`、`chalkboard`、`microchip`、`glass`、
`holographic`、`paper`、`retro`、`xray` 等),并且在使用 `custom-style` 时,微调
`macos-icon-frame` 以及 `macos-icon-ghost-color` / `macos-icon-screen-color`
(这些会显示实时色板)。请参阅图标库:
。
## 配置文件和配置医生
**配置文件** 是您整个配置的命名快照 —— 在 TUI 中按 `p`(或
使用 `spookiui profile …`)保存当前设置,以后再加载回来。
保存一个 `light` 和一个 `dark` 配置文件,然后使用 `t` 键(或 `spookiui profile
toggle`)即可在它们之间瞬间切换。加载配置文件会经过验证,并首先备份
您当前的配置,就像其他所有更改一样。配置文件位于
`$XDG_DATA_HOME/spookiui/profiles`(默认为 `~/.local/share/…`),位于
Ghostty 自己的配置目录之外,因此它永远不会读取它们。
**`spookiui doctor`**(或在 TUI 中按 `c`)会对您的配置进行健康检查并报告:
无效的设置、未知/拼写错误的选项、设置了多次的选项(无效
行)、仅仅是重复默认值的设置,以及绑定了两次或覆盖了 Ghostty 默认值的快捷键触发器。检查结果按严重程度分组;当存在错误时,它会以非零状态退出,因此它可以完美地
作为 dotfiles 的 pre-commit 钩子。
## 实用工具 —— 一次性修复
**⚙ Utils** 类别(左侧面板中的最后一个条目,或者在任意位置按 `v`)
收集了一些小型的、一次性的维护操作,它们并不是 Ghostty 的配置选项。
高亮显示一个操作即可阅读其功能说明;按 `Enter`/`→` 运行它。
### 修复 SSH
Ghostty 告诉程序它是 **`xterm-ghostty`**(通过 `TERM` 变量)。当
您通过 SSH 登录到另一台机器时,该主机会在**它自己的**
terminfo 数据库中查找 `xterm-ghostty` —— 而大多数远程主机从未听说过它。远程
shell 随后会出现异常行为:按键乱码或失效、颜色缺失、
`clear`/`tput` 损坏,或者出现经典的 `Error opening terminal: xterm-ghostty`。
**Fix SSH** 会在您的 shell rc(`~/.zshrc` 或 `~/.bashrc`,与您的登录
shell 匹配的那个)中添加一行代码:
```
alias ssh="TERM=xterm-256color ssh"
```
这样 `ssh` 命令就会使用 **`xterm-256color`** 运行 —— 这是一个基本上每台主机
都已经自带的 terminfo 条目。您本地的 Ghostty 会话保留了其完整的
`xterm-ghostty` 特性;只有出站的 SSH 连接被降级为这个
普遍认可的值。远程主机上的任何内容都不会被更改。
它是**安全且幂等的**:它会首先扫描您的 shell rc 文件(`.zshrc`、
`.bashrc`、`.bash_profile` 等),如果别名已存在,则不执行任何操作;否则,它会追加该行代码并对文件进行语法检查。由于正在运行的 shell
无法从外部修改,它会提示您 `source` 该文件或打开
一个新终端以使别名生效。要撤销此操作,请删除该别名行。(一种
更彻底的替代方法是将 Ghostty 的 terminfo 复制到每台主机,但此
别名是无需远程访问的快速修复方案。)
也可以从命令行 (CLI) 运行:
```
./spookiui.py fix-ssh # add the alias if it's missing
./spookiui.py fix-ssh --check # report whether it's present; change nothing
./spookiui.py fix-ssh --explain # print the full what/why, then exit
```
## 可脚本化的 CLI
TUI 执行的所有操作也都可以通过非交互方式完成:
```
./spookiui.py list [category] # list options (* = changed from default)
./spookiui.py list [category] --all # include options for the other OS
./spookiui.py get # print an option's current value
./spookiui.py doc # show an option's documentation + choices
./spookiui.py set … # set (writes + reloads live); repeat value for lists
./spookiui.py set --no-reload # write without reloading
./spookiui.py reset --yes # clear config & restore all Ghostty defaults (backup kept)
./spookiui.py version # print version & check GitHub for a newer release
./spookiui.py update # update in place to the latest release (git pull or download)
./spookiui.py profile save # snapshot the current config as a named profile
./spookiui.py profile load # apply a saved profile (validated, backed up)
./spookiui.py profile list # list saved profiles (also: show / delete / toggle)
./spookiui.py profile toggle # flip between the 'light' and 'dark' profiles
./spookiui.py doctor # health-check the config (duplicates, unknown keys, keybind clashes…)
./spookiui.py fix-ssh # fix garbled SSH sessions (adds a TERM=xterm-256color ssh alias)
./spookiui.py fix-ssh --check # report whether the SSH alias is present; change nothing
./spookiui.py reload # trigger a live reload
./spookiui.py validate # validate the current config
./spookiui.py themes # list installed themes
./spookiui.py fonts # list monospace font families
./spookiui.py path # print the config file in use
```
示例:
```
./spookiui.py set theme "Catppuccin Latte"
./spookiui.py set font-size 15
./spookiui.py set font-family "JetBrains Mono" "Symbols Nerd Font" # primary + fallback
./spookiui.py doc background-opacity
```
## 注意事项与限制
- **实时重载适用于 macOS 和 Linux**(并在其他平台上安全降级) —— 请
参阅上方的[各平台的实时重载](#live-reload-by-platform)以了解特定于操作系统的
机制和要求。
- 对单值选项的编辑是**就地**进行的,保留了您文件中的
注释和布局。新选项和列表选项会被写入到明确标记的
`# added by SpookiUI` 部分下。
- 配置路径是自动检测的(`$XDG_CONFIG_HOME/ghostty/config`,然后是
`~/.config/ghostty/config`,最后是 macOS 的应用支持路径)。
## 更新
SpookiUI 在启动时会静默检查 GitHub 上是否有更新的版本。如果有更新,TUI 会在页眉处显示一个 `⬆ UPDATE vX.Y.Z` 徽章(并在状态栏显示 *按 `U` 更新*);帮助屏幕 (`?`) 始终显示您当前的版本。随时运行
`spookiui version` 以按需检查。
此检查是**尽力而为且非阻塞的** —— 它在后台线程上运行,
会迅速超时,并在您离线或无法访问 GitHub 时保持静默。
结果会缓存一天(位于 `$XDG_CACHE_HOME/spookiui/` 下),因此它绝不会
频繁请求 API。要完全关闭此功能,请设置 `SPOOKIUI_NO_UPDATE_CHECK=1`。
### 就地更新 —— 无需 `git pull`
在 TUI 中按 `U`,或运行 `spookiui update`。不涉及任何更新服务器 ——
GitHub 是源,而 SpookiUI 是一个单文件,因此更新只是替换该
文件:
- **Git checkout**(默认的 `install.sh` 布局) → 它会为您运行 `git pull`。
- **独立副本** → 它会下载最新版本的 `spookiui.py`,*验证
其可编译性*,然后原子地替换该文件(保留 `.prev` 备份)。截断或
错误的下载绝不会让您得到一个损坏的工具。
- **无写入权限**(例如以 root 身份进行的系统级安装) → 它会告诉您
需要运行的确切命令,而不是静默失败。
之后重新启动 SpookiUI 以运行新版本。
维护者:通知和更新只会在发布了匹配的
**GitHub Release** 后才会采用新版本 —— 有关版本升级和发布流程,请参阅 [`RELEASING.md`](RELEASING.md)。
## 许可证
MIT —— 请参阅 [`LICENSE`](LICENSE)。
标签:Python, 命令行界面, 无后门, 桌面工具, 终端工具, 逆向工具