OpenCode 内置了许多适用于浅色和深色模式的主题。可在设置中选择其中一个,或自行搭配颜色。
选择主题
按下
Ctrl+P,选择 Open settings,然后打开 Theme。默认主题是 opencode。也可以在全局 CLI 设置中指定主题和模式:
{
"$schema": "https://opencode.ai/v2/cli.json",
"theme": {
"name": "tokyonight",
"mode": "dark"
}
}
运行
/themes 即可在不打开设置的情况下切换主题。系统颜色
当 OpenCode 能够读取终端调色板时,主题选择器会包含
system 主题。它会根据终端的前景色、背景色和 ANSI 调色板推导颜色。主题名
system 表示使用从终端推导出的颜色。模式 system 则跟随终端的浅色或深色外观。模式
使用
system 可跟随终端外观,也可以将主题锁定为浅色或深色模式:| 模式 | 行为 |
| --- | --- |
|
system | 跟随终端检测到的浅色或深色外观。 |
| dark | 始终使用主题的深色配色。 |
| light | 始终使用主题的浅色配色。 |这对应 CLI 配置中
theme 内的 mode 字段。如果自定义主题仅提供一种模式,当请求另一种模式时,OpenCode 会使用已有的那种模式。添加主题
要添加下载或从他人处获得的主题,请将其 JSON 文件复制到全局主题目录:
cp theme.json ~/.config/opencode/themes/
也可以将主题放在项目的
.opencode/themes 目录中,使其仅在该项目中可用。文件名即为主题名。例如,
my-theme.json 会显示为 my-theme。添加文件后请重启 OpenCode,然后运行 /themes 选择该主题。OpenCode 仅读取
.json 文件。更靠近当前目录的主题会覆盖同名的全局或上级目录主题。在插件中使用主题
import { usePlugin } from "@opencode/plugin/tui"
function Status() {
const context = usePlugin()
return <text fg={context.theme.text.base}>Ready</text>
}
公开的 CLI 插件 API 不注册主题。请使用上述目录中的 JSON 文件添加自定义主题定义。
创建主题
使用我们的主题工具创建或编辑主题。该工具便于理解主题结构、进行修改并定义自定义颜色。以下说明仅供参考。
主题将共享的语义化 token 与各模式专属的调色板分开:
| 部分 | 用途 |
| --- | --- |
|
base | 所有模式共享的完整 token 树。 |
| light、dark | 该模式的完整色相调色板以及可选的 token 覆盖。 |每个主题都要提供完整的
base,并至少定义 light 或 dark 之一。各模式继承文件中的 base;它们不会继承内置的 OpenCode 主题,也不会相互继承。以下示例仅展示与各概念相关的部分。请先用主题编辑器生成完整文件,再进行自定义。
结构
将两种模式共用的颜色放在
base 中,需要时再在 light 或 dark 内覆盖:{
"$schema": "https://opencode.ai/theme.json",
"base": {
"text": {
"base": "$hue.neutral.200",
"muted": "$hue.neutral.400"
}
},
"light": {
"hue": {}
},
"dark": {
"hue": {},
"text": {
"muted": "$hue.neutral.300"
}
}
}
完整的
base 提供所有语义化 token。每个模式提供所有必需的色相,并可覆盖 base token 树的任意部分。颜色与引用
颜色可以是十六进制值、
"transparent",或对其他主题颜色的引用:{
"text": {
"base": "#eeeeee",
"muted": "$hue.neutral.400"
},
"border": {
"base": "$text.muted"
}
}
色相
色相是九级色阶。每个模式定义八个基础色相和三个别名:
| 类型 | 值 |
| --- | --- |
| 基础 |
gray、red、orange、yellow、green、cyan、blue、purple |
| 别名 | accent、interactive、neutral |
| 级别 | 100、200、300、400、500、600、700、800、900 |为基础色相定义全部九级,或将一个色相指向另一个色相作为别名:
{
"hue": {
"purple": {
"100": "#b38ff4",
"200": "#9d7cd8",
"300": "#8869bd",
"400": "#7357a2",
"500": "#5f4688",
"600": "#4b356f",
"700": "#392557",
"800": "#271640",
"900": "#17072b"
},
"accent": "$hue.purple"
}
}
色相级别遵循模式的对比度方向。浅色主题从
100 的深色过渡到 900 的浅色;深色主题从 100 的浅色过渡到 900 的深色。base 中的 categorical 数组设置用于区分智能体及其他重复项的有序色相:{
"categorical": ["accent", "purple", "green", "blue"]
}
语义化 token
语义化 token 将颜色分配给 UI 角色。组件使用这些角色,而非直接选择颜色。
| 分组 | 用途 |
| --- | --- |
|
text | 基础、弱化、极弱、操作、表单字段和反馈文本。faint 默认取 muted。 |
| background | 基础、抬升表面、操作、表单字段和反馈填充。 |
| border、scrollbar | 边框和滚动条颜色。 |
| diff | 新增、删除、上下文、高亮和行号颜色。 |
| syntax | 源代码高亮。 |
| markdown | Markdown 元素。 |例如,
text.muted 控制次要文本,而 background.raised 定义逐级抬升的表面:{
"text": {
"base": "$hue.neutral.200",
"muted": "$hue.neutral.400"
},
"background": {
"base": "$hue.neutral.800",
"raised": {
"base": "$hue.neutral.700",
"high": "$hue.neutral.600",
"max": "$hue.neutral.500"
}
}
}
Syntax 键包括
comment、keyword、function、variable、string、number、type、operator 和 punctuation。Markdown 键包括
text、heading、link、linkText、code、blockQuote、emphasis、strong、horizontalRule、listItem、listEnumeration、image、imageText 和 codeBlock。操作与状态
操作分为
primary、secondary 和 destructive 三种变体。操作和表单字段使用 base,外加可选的交互状态:{
"text": {
"action": {
"primary": {
"base": "$hue.interactive.400",
"$hovered": "$hue.interactive.300",
"$disabled": "$hue.neutral.600"
}
}
}
}
状态键为
$hovered、$focused、$pressed、$selected 和 $disabled。未指定的状态沿用该操作或表单字段的 base 颜色。对话框表面
面板、对话框、菜单和 toast 从
background.raised 选取其深度。对话框还可以通过 @dialog 额外覆盖语义化 token:{
"@dialog": {
"background": {
"base": "$background.raised.base",
"action": {
"primary": {
"$hovered": "$background.raised.high"
}
}
}
}
}
TUI 在应用
@dialog 后会重新解析引用,因此引用 $background.base 的 token 会跟随对话框背景。上下文操作的 base 会成为其未指定状态的回退值;显式的状态覆盖仍然优先生效。