Install
openclaw skills install @hanhan1137/ui-theme-coach引导式 UI 主题设计顾问:通过问答引导帮用户定制任意风格的 OpenClaw Control UI 主题(像素/赛博朋克/卡通/极简/暗色科技等),含主色派生调色板、双保险注入、升级自愈(cron+快照)与反馈学习循环。触发词:主题、换皮、皮肤、UI 美化、风格。
openclaw skills install @hanhan1137/ui-theme-coach引导式 UI 主题设计 skill:通过问答引导帮用户定制任意风格的 OpenClaw Control UI 主题。 五大能力:通用方法论、风格技术库、自助检索、升级自愈、反馈学习。
一次 2-3 个问题:
用户给不出就推荐默认:通用像素风 + 深色 + 一个主色。
核心规则:只要用户给出了具体风格/IP/参考(赛博朋克、Minecraft、极简、卡通、暗色科技、某知名 IP 等),在进入设计令牌之前,先查这个风格的资料。不查就设计 = 靠印象硬做,还原度会飘。
查什么(web_search / web_fetch):
查完产出(调研小结,写进设计依据):
data/style-refs.json 或本目录,方便复查)优先级: 用户给的风格越具体 → 调研越认真;用户给的是宽泛方向(如"想要温馨点")→ 可轻查或不查,直接走内置风格库(references/styles/)。
内置风格库(第四步)是兜底,不是代替调研——两者互补:调研给还原度,内置库给实现技巧。
| 变量 | 作用 |
|---|---|
--bg / --bg-elevated / --bg-muted / --bg-content / --bg-hover | 背景层级(含悬停) |
--card / --card-foreground | 卡片底色/文字 |
--chat-text / --chat-box-inset | 聊天文字/输入框底 |
--border / --border-hover / --border-strong | 边框 |
--accent / --accent-hover / --accent-muted / --accent-foreground | 强调色 |
--accent-glow | 辉光 |
--accent-2 / --accent-2-muted / --accent-2-subtle | 第二强调色 |
通用设计令牌:这套变量名继承自 OpenClaw Control UI 的令牌约定,但本身是通用设计令牌——任何 Web UI 拿到这 20 个变量都能直接消费。目标 UI 用别的变量名时,按语义映射过去即可(如
--bg→对方的主背景变量)。这保证了本 skill 的设计成果不只用于 Control UI,也可交付给任意 Web 项目(见 3.0 目标环境判定)。
方法 A:HSL 偏移(Python 标准库,零依赖)
从主色 hex 提取 HSL,保持色相、阶梯亮度,自动派生 20 个 CSS 变量。默认深色主题;浅色主题加 --light 亮度反转(背景转浅、文字转深、主色不变):
python3 scripts/derive-palette.py '#7ca843' # 深色(默认)
python3 scripts/derive-palette.py '#7ca843' --light # 浅色(亮度反转)
两种模式派生的变量都要过第四步「必查配对清单」;浅色版
--accent-foreground特意保持深字,与中亮度强调色保证 ≥ 4.5:1;border 类单独处理:以最终--bg为基准自动二分对齐对比度(--border≈3.2:1 /--border-strong≈4.2:1 /--border-hover≈5.5:1,任意色相都过 UI 组件 ≥3:1 且不刺眼)。非法 hex(缺#/3 位简写/非 hex 字符)脚本会友好报错并打印用法,不会吐 Python traceback。 完整脚本见scripts/derive-palette.py。
方法 B:OKLCH(色彩空间更均匀,需要额外库) 同样思路但用 OKLCH 插值,渐变更自然。
选择方法 A/B 取决于用户偏好;方法 A 零依赖够用。
通用方法论(v1.3.0 起,源自 DSH 适配版回合):本 skill 不只服务 OpenClaw Control UI。动手前先判定目标形态,按形态选交付方式:
| 目标形态 | 判定方式 | 交付形态 |
|---|---|---|
| A. 构建产物 index.html(OpenClaw Control UI / DSH web UI 即此类:静态入口文件 + 会被升级覆盖) | 目标存在一个会被构建/升级覆盖的静态入口文件 | 3.1 双保险注入 + 备份 + 主题包快照(7.0) |
| B. 静态原型/设计稿 | 用户只要效果,没有固定宿主 | 直接产出完整 HTML/CSS(单文件或小项目),无需注入 |
| C. 其他运行时(非 Web/插件体系) | 目标不是浏览器页面 | 只做设计令牌 + 配色方案(第二步产物),实现细节按目标环境调整 |
本 skill 的主场景 = 形态 A 的 OpenClaw Control UI(注入架构见 3.1,自愈见 3.2)。形态 A 的注入步骤是通用 Web 技术,用于其他目标时,注入位置、资源路径必须按实际目标环境核对(备份→注入→验证三件套不变)。
双保险注入法:
</head> 前加 <style> 定义 :root 变量</body> 前加 <script>:ensureDocStyle() + WeakSet + MutationObserver 递归遍历所有 shadow root(shadow root 套 shadow root 的套娃也钻进去,见 minecraft-example.md 的 walk())references/minecraft-example.md问题:OpenClaw dist 升级会覆盖
dist/control-ui/index.html,主题注入丢失。 解决:注入时留指纹 + 存快照 → 检测到指纹缺失则自动从快照重新注入。 自愈闭环 = 注入 + 快照 + cron + 验证,四步缺一不可。
实现(注入 → 快照 → 自愈,按顺序全部必做):
<style> 与 <script> 块必须带三个属性——data-theme-id="<主题名>"(识别装的哪个主题)、data-theme-version="<主题版本>"(主题自身版本)、data-upstream-version="<注入时的 dist 上游版本>"(从 OpenClaw package.json 的 version 字段读,如 2026.7.1-2);heal.sh 靠前两个判断「当前装的是哪个主题、有没有丢」,靠第三个在重注入前做上游版本比对~/.openclaw/workspace/theme-coach/snapshot/<主题名>/,且只存这两个文件、文件名固定:
theme-vars.html:注入到 </head> 前的内容(含指纹的 <style> 块)injector.html:注入到 </body> 前的内容(含指纹的 <script> 块)scripts/heal.sh:自动探测 OpenClaw 安装路径(不硬编码);检查指纹 → 缺失则从快照恢复;同主题跳过、不同主题明确报出(先 heal.sh uninstall 再重灌);heal.sh uninstall [主题名] 卸载还原原版;--force 切换时先验目标快照(目录 + 契约文件 + 指纹全对上)再卸载旧主题——目标快照缺失/契约违反直接报错退出(exit 非 0),现有主题原样不动;重注入前比对 data-upstream-version 与当前 dist 版本,主版本跳大先警告再注入(DOM/CSS 钩子可能已变,注入后必须人工验证;样式坏了就按新 dist 重做快照)( crontab -l 2>/dev/null | grep -v 'heal.sh' ; echo '0 6 * * * /bin/bash "<skill 安装目录>/scripts/heal.sh" <主题名> >> ~/.openclaw/workspace/theme-coach/heal.log 2>&1' ) | crontab -
crontab -l | grep heal.sh # 确认注册成功
<skill 安装目录>换成 skill 实际路径(在 skill 目录里执行pwd即得);<主题名>换成刚注入的主题。改现有 crontab 前必须先crontab -l看现状。
bash "<skill 安装目录>/scripts/heal.sh" <主题名>,输出应为 [heal] Theme '<主题名>' is present, skipping.——确认「已注入状态能被自愈脚本正确识别」后闭环才算成立。只注册不验证 = 没做;以后可用 tail ~/.openclaw/workspace/theme-coach/heal.log 查看每日自检结果换主题/还原默认都走
scripts/heal.sh,与自愈共用同一套指纹 + 快照机制,不需要手工删注入块。<skill 安装目录>= 本 skill 实际安装位置(在 skill 目录里pwd即得)。
切换主题(A → B,B 已有快照):
bash "<skill 安装目录>/scripts/heal.sh" B——检测到当前装的是 A 会明确报出并退出(不静默覆盖)bash "<skill 安装目录>/scripts/heal.sh" B --force(能力细节见 3.2 第 3 条:先验目标快照 → 卸载 A → 注入 B,全程自动备份 + 上游版本比对,此处不再重复)crontab -l | sed 's#heal.sh" A#heal.sh" B#' | crontab - # A/B 换成实际主题名
crontab -l | grep heal.sh # 确认已更新
还原默认(摘掉主题,回到 OpenClaw 原版 UI):
bash "<skill 安装目录>/scripts/heal.sh" uninstall [主题名]——主题名省略 = 自动检测当前注入的主题;自动备份(index.html.bak-heal-<时间戳>)后移除带指纹的 <style>/<script> 注入块( crontab -l 2>/dev/null | grep -v 'heal.sh' ) | crontab -
注意:uninstall 只摘注入块,不动快照目录(以后想换回来直接 --force 秒切);切换/还原属于改变用户环境的操作,动手前先跟用户确认。
pointer-events: none 不挡点击dist/control-ui/index.html,可回滚contrast-check.py,全部达标每种风格的技术要点 + 反模式都拆成独立模板存在
references/styles/<风格>.md,SKILL.md 不再内嵌风格数据——社区加新风格只加一个文件,不用改主文件。
加载流程(必做):
ls references/styles/ 看当前有哪些风格模板(TEMPLATE.md 是新增风格用的空模板)TEMPLATE.md 复制一份填好)pixel-game(像素/游戏)/ cyberpunk(赛博/霓虹)/ cartoon-cute(卡通/可爱)/ minimal-modern(极简/现代)/ dark-tech(暗色科技)——以 ls 实际结果为准<风格>.md 自带「反模式」节:用哪个风格就读哪个风格的反模式,逐条自查这些是真实踩过的坑,不是泛泛之谈。每次交付前对着自查:
scripts/contrast-check.py只查一对不算数。下面每对文字-背景配对都必须用
python3 scripts/contrast-check.py <文字色> <背景色> "<标签>"跑一遍,全部达标才交付:
| 文字变量 | 背景变量 | 要求 |
|---|---|---|
--chat-text | --bg | ≥ 4.5:1 |
--chat-text | --bg-content | ≥ 4.5:1 |
--chat-text | --card | ≥ 4.5:1 |
--chat-text | --chat-box-inset | ≥ 4.5:1 |
--card-foreground | --card | ≥ 4.5:1 |
--accent-foreground | --accent | ≥ 4.5:1 |
--accent-foreground | --accent-hover | ≥ 4.5:1 |
| 非文字 | --border vs --bg | ≥ 3:1(UI 组件) |
| 非文字 | --border-strong vs --bg | ≥ 3:1(UI 组件) |
| 非文字 | --border-hover vs --bg | ≥ 3:1(UI 组件) |
derive-palette.py 派生已自动对齐 ≥3:1(贴 3.2 不刺眼),但风格化需要(更低调/更亮的描边、双线边框等)改完后必须重跑本清单,确认 --border/--border-strong/--border-hover 对 --bg 仍 ≥3:1 才交付内置工具箱只是兜底。不熟风格/更高还原度时,主动"觅食"。注意:用户给了具体风格时,这一步(查风格资料)应在设计前就先做(见第一步·补),这里是查字体/纹理/图标/CSS 技巧等实现细节。
用户要某 IP/风格(Hello Kitty、MC、某游戏、某动画等)时,默认路径 = 帮用户找到官方/授权素材(自绘只是兜底,见下)。官方渠道通常自带「个人使用授权」(如 Sanrio 官方壁纸专区、IP 官方素材页),比自绘/野图更贴原版、更好看。
自绘降级判定(仅在以下情况才自绘):① 用户明确要求自绘/原创;② 官方素材不可得(无官方渠道/无授权下载);③ 用户提供不了可用图。否则一律走官方素材。
流程:
边界(红线真正的位置):
不只是一次性顾问,持续学习用户偏好。
机制:
data/feedback.json(统一落点:跟 skill 走,开源/迁移不丢偏好;skill 目录 = 实际安装位置,在目录里 pwd 即得):
{
"preferences": { "style": "pixel-game", "baseColor": "#7ca843",
"likes": ["readable-textures", "border-image-buttons"],
"dislikes": ["gradients"],
"accessibility": true },
"history": [ { "theme": "mc-pixel", "date": "2026-08-09", "rating": "positive" } ]
}
无论注入到哪个目标(Control UI / 任意 Web 项目),交付物建议打包成标准主题包——它就是「快照的通用化形态」:
<主题名>-theme/
├── theme-vars.html # :root 变量注入块(带 data-theme-id 指纹)
├── injector.html # 样式注入器(带指纹,见 references/minecraft-example.md)
├── assets/ # 字体/纹理/图标(内置素材须自绘或已授权;用户自备素材放用户侧,不打包)
└── README.md # 风格说明 + 安装步骤(3.1/3.2·补)+ 对比度实测表
theme-vars.html / injector.html 与注入目标的内容逐字节一致(升级覆盖后靠它重灌)~/.openclaw/workspace/theme-coach/snapshot/<主题名>/)就是主题包的本地落点,两者是同一套东西references/open-source-checklist.mdderive-palette.py <hex> --light)references/styles/ 对应风格模板(ls 找);没有→调研+自助检索contrast-check.py 全部达标theme-vars.html + injector.html 固定文件名、带 data-theme-id/data-theme-version/data-upstream-version 指纹、目录无草稿heal.sh <主题名> 验证闭环heal.sh <新主题> --force、还原默认用 heal.sh uninstall,切换后同步 cron 主题名(见 3.2·补)data/feedback.json(统一落点)references/minecraft-example.md:完整 MC 像素风 Worked Examplereferences/styles/:风格技术库(每种风格的技术要点+反模式独立模板,含 TEMPLATE.md 新风格模板)scripts/derive-palette.py:HSL 主色派生脚本(实出 20 个 CSS 变量;默认深色,--light 亮度反转出浅色版;border 类自动对齐 UI 组件 ≥3:1;非法 hex 友好报错)scripts/contrast-check.py:WCAG 对比度检查脚本(第四步必查配对清单逐对跑;非法 hex 友好报错)scripts/heal.sh:升级自愈脚本(heal 自愈 / --force 切换 / uninstall 还原三用法,自动探测安装路径 + 指纹识别主题 + --force 先验目标快照再卸载 + 重注入前上游版本比对;工作流见 3.2·补)test-prompts.json:达尔文自测用例(6 条:3 happy path + 3 负面/边界——测试偏好红线/模糊输入/切换还原路径),每次改完用其验证流程通不通