专门为 @bachi/pi-coder 定制的三套暗色 PI 主题 —— 调色板分别取自 catppuccin mocha、ayu dark 与 iceberg.vim 的 dark 形态,面向 mac retina 屏完成微调,适配深夜编程体验。
皮肤源文件来自 @bachi/pi-coder,展示页色值取自 themes 目录下三个 pi-coder- 前缀的皮肤文件,
点击任意色块可复制其十六进制值。底部有 PI 着色预览。
这是一套自建主题:底色是压暗的深蓝黑 #1A1B26,前景为偏冷的灰白 fg #C6C8D1;关键字与行内代码走紫 moonLilac #A093C7,类型与强调落在亮青 sky #95C4CE,函数与运算符另有蓝系两支,字符串绿、数字黄。工具卡片、userMessage、diff 底色沿用上一版;代码注释提亮一档。
| 槽位 | 色块 | hex |
|---|---|---|
| 主底色night | #1A1B26 | |
| 用户消息底userMessageBg | #1B1C1D | |
| 自定义消息底customMessageBg | #2B2B3B | |
| 选中行selectedBg | #2D2C5D | |
| 工具待执行toolPendingBg | #101017 | |
| 工具成功底toolSuccessBg | #11171D | |
| 工具失败底toolErrorBg | #191319 |
| 槽位 | 色块 | hex |
|---|---|---|
| 差异新增底toolDiffAddedBg | #1C241B | |
| 差异删除底toolDiffRemovedBg | #2E1C21 | |
| 边框border | #515E97 | |
| 弱边框borderMuted | #2A3158 | |
| 导出页底export.pageBg | #16161E | |
| 导出卡片export.cardBg | #1A1B26 | |
| 导出信息底export.infoBg | #2D2C5D |
// pi-coder-summer-night · syntax sampler import { Skin } from "./theme.js"; const palette = await load("pi-coder-summer-night"); export default class SummerNight extends Skin { levels = [0, 25, 50, 75, 100]; // 思考强度阶梯 mix(a, b) { return a.map((v, i) => (v + b[i]) / 2); } }
文件 themes/pi-coder-summer-night.json · 40 个变量、59 个槽位赋值。
colors 里没有一个字面量色值,全部引用 vars。调色板以 iceberg.vim 的 dark 分支为底:26 个变量是它的字面值(折 21 个色值、5 组同值)、1 个是按 comment 算出来的 commentBright、12 个是上一版保留的底色、1 个是后加的 diff 新增行前景 addedGreen。
槽位映射只动了一处:toolDiffAdded 由 teal 改指 addedGreen(#8BC391)。
在官方 Catppuccin Mocha 基础上面向 retina 屏做了大量微调,三档深底(crust / mantle / base)撑起层次。唯一一处"越界"是强调色:用的是 Macchiato 的 lavender #B7BDF8(重命名为 macchiatoLavender),而不是 Mocha 自己的 mauve —— mauve 被降级去当工具标题与关键字。
| 槽位 | 色块 | hex |
|---|---|---|
| 页面底色bg (base) | #1E1E2E | |
| 用户消息底userMessageBg (mantle) | #181825 | |
| 自定义消息底customMessageBg (mantle) | #181825 | |
| 选中行selectedBg | #1E1E29 | |
| 工具待执行toolPendingBg | #0B151F | |
| 工具成功底toolSuccessBg | #151515 | |
| 工具失败底toolErrorBg | #171010 |
| 槽位 | 色块 | hex |
|---|---|---|
| 差异新增底diffAddedBg | #1C241B | |
| 差异删除底diffRemovedBg | #2E1C21 | |
| 边框border (surface1) | #45475A | |
| 弱边框borderMuted (surface0) | #313244 | |
| 导出页底export.pageBg (crust) | #11111B | |
| 导出卡片export.cardBg (mantle) | #181825 | |
| 导出信息底export.infoBg | #242031 |
// pi-coder-catppuccin · syntax sampler import { Skin } from "./theme.js"; const palette = await load("pi-coder-catppuccin"); export default class Catppuccin extends Skin { levels = [0, 25, 50, 75, 100]; // 思考强度阶梯 mix(a, b) { return a.map((v, i) => (v + b[i]) / 2); } }
文件 themes/pi-coder-catppuccin.json · 36 个变量(26 个上游 Mocha + 10 个本地新增)、54 个槽位赋值。
值得注意的几处偏移:error 用 maroon #EBA0AC 而非 red;syntaxFunction 用 sky 而非 blue;三个工具面板色(#151515 / #171010 / #0B151F)是自造的近黑,比 Mocha 的 surface 系更沉。
一整套暖橙 + 青蓝的主题,灰阶和主色调都做了微调。语法槽位贴着官方 ayu Dark 走(10 个角色对齐后平均 ΔE 只有 1.72),灰阶与面板是自家第三套值,比 Dark 更沉。字符串没有用官方的 #AAD94C,而是压暗到 stringGreen #67A567。
| 槽位 | 色块 | hex |
|---|---|---|
| 页面底色bg | #0D1017 | |
| 用户消息底userMessageBg | #1B1C1D | |
| 自定义消息底customMessageBg | #1B1C1D | |
| 选中行selectedBg | #161D2B | |
| 工具待执行toolPendingBg | #1B1C1D | |
| 工具成功底toolSuccessBg | #10151F | |
| 工具失败底toolErrorBg | #1B171D |
| 槽位 | 色块 | hex |
|---|---|---|
| 差异新增底diffAddedBg | #1D241C | |
| 差异删除底diffRemovedBg | #321D23 | |
| 边框border (dimmed) | #515868 | |
| 弱边框borderMuted | #232938 | |
| 导出页底export.pageBg | #0B0E14 | |
| 导出卡片export.cardBg | #0D1017 | |
| 导出信息底export.infoBg | #1A1610 |
// pi-coder-ayu · syntax sampler import { Skin } from "./theme.js"; const palette = await load("pi-coder-ayu"); export default class Ayu extends Skin { levels = [0, 25, 50, 75, 100]; // 思考强度阶梯 mix(a, b) { return a.map((v, i) => (v + b[i]) / 2); } }
文件 themes/pi-coder-ayu.json · 30 个变量、55 个槽位赋值。
xhigh 与 max 同色(#626262),也是三套里唯一把高思考档画成中灰而非彩色的。相比于官方 ayu 色系做了大量的调整,主要是代码块 diff 和 pi 工具调用色块的底色等等做了调整。
同一槽位、三套取值。点色块复制 hex。
| 槽位 | summer-night | catppuccin | ayu |
|---|---|---|---|
| 底色bg | #1A1B26night |
#1E1E2Ebase |
#0D1017bg |
| 前景text | #C6C8D1fg |
#CDD6F4text |
#BFBDB6fg |
| 强调色accent | #95C4CEsky |
#B7BDF8macchiatoLavender |
#E6B450accent |
| 成功success | #89B8C2teal |
#A6E3A1green |
#AAD94Cgreen |
| 错误error | #E27878red |
#EBA0ACmaroon |
#D95757red |
| 警告warning | #E2A478yellow |
#FAB387peach |
#FF8F40orange |
| 关键字syntaxKeyword | #A093C7moonLilac |
#CBA6F7mauve |
#FF8F40orange |
| 字符串syntaxString | #B4BE82green |
#A6E3A1green |
#67A567stringGreen |
| 函数名syntaxFunction | #84A0C6blue |
#89DCEBsky |
#FFB454function |
| 注释syntaxComment | #6E7DC0commentBright |
#A6ADC8subtext0 |
#6B7385muted |
| 面板底userMessageBg | #1B1C1DayuUserBg |
#181825mantle |
#1B1C1DuserMessageBg |
| 选中行selectedBg | #2D2C5Dselect |
#1E1E29selected |
#161D2BselectedBg |
每块色板里出现的两类名字,含义并不相同。
主题 JSON 里 vars 的键,是这套配色自己的命名 —— moonLilac、macchiatoLavender、stringGreen 之类。它只对这套皮肤有意义,换一套皮肤同一个名字不会出现。
pi 主题 schema 里 colors 的固定键 —— accent / success / mdLink / syntaxString …… 三个皮肤必须各自给出同一批键的取值,这才是三套配色之间唯一可比的层。上文对照表即参照于此。
每块色板内的标签用黑或白,按 WCAG 相对亮度二选一,取对比度更高者;底部边缘接近 1:1 的深底一律用白字。这不是皮肤的一部分,只是这张表的排版规则。
取自一次真实会话:上半是聊天区,下半是 pi 的输入框、任务清单和 statusline。点下面的按钮换皮肤。
server.js 已从 HTTP 切到 HTTPS,其余逻辑(/api/ 反代、MIME、目录穿越防护)未动。
server.js:新增 TLS_OPTIONS 加载 cert/abc.com+5.pem / cert/abc.com+5-key.pem,入口改为 https.createServer(TLS_OPTIONS, handleRequest)。CLAUDE.md:更新启动命令注释、协议说明和文件表里 server.js / cert/ 两行。其他三份实现(Go / Rust / Python)仍是 HTTP,未改 —— 详见 README。
输入框上方那行是 simple-task 的任务清单(已完成的 ✔ 用 success、正文用 dim 加删除线),下面依次是
pi 的输入框(边框与 ❯ 取当前思考档的颜色,这里是 max → 本主题的 thinkingMax;左上一段是工作指示器嵌在边框里的样子)
与 statusline 两行: ⚡️ 模型/档位 | Ctx 百分比 | 分支 | (+增,-删) | 状态,第二行是所有扩展 setStatus 的文本(任务计数、cwd)。
分支图标用的是 ⎇(U+2387,通用符号区,没装 Nerd Font 的机器也能正常显示)。