Model: claude-opus-4-6 (anthropic/claude-opus-4-6) Generated: 2026-04-03 Book: Claude Code VS OpenCode: Architecture, Design and The Road Ahead 章节: 第12章 — 解剖一个13万行代码的插件 Token Usage: ~120,000 input + ~6,200 output
12.6 配置分层
为什么配置系统重要?
41 个 hook、26 个工具、11 个智能体——如果没有好的配置系统,用户根本无法管理。想象 100 个按钮的遥控器没有说明书、没有分组、按错一个全部失灵。
三层配置模型
📁 文件说明:
src/plugin-config.ts配置加载实现。从多个位置读取、合并、校验,并处理配置损坏。
flowchart TD
D["Layer 1: Defaults<br/>Code defaults + schema optionals"] --> U
U["Layer 2: User Config<br/>~/.config/opencode/oh-my-opencode.jsonc"] --> P
P["Layer 3: Project Config<br/>.opencode/oh-my-opencode.jsonc"]
P --> Final["Final Effective Config"]
U -->|"overridden by"| Final
D -->|"fallback"| Final
| 层级 | 类比 | 作用域 |
|---|---|---|
| 默认值 | 出厂设置 | 兜底 |
| 用户级 | 个人偏好 | 所有项目 |
| 项目级 | 项目特殊要求 | 仅当前项目 |
OMO 三层 + OpenCode 宿主配置 = 共存:
graph TD
subgraph OMO_Config["OMO 3 Layers"]
L1["defaults"]
L2["user config"]
L3["project config"]
end
subgraph OC_Config["OpenCode Host Config"]
H1["agents"]
H2["tools"]
H3["mcp"]
H4["commands"]
H5["permissions"]
H6["providers"]
end
OMO_Config -->|"config hook<br/>injects into"| OC_Config
22 个 Schema 文件
📁 文件说明:
src/config/schema/目录 22 个 Zod v4 schema 文件,按责任边界拆分。
graph TD
Root["oh-my-opencode-config.ts"]
Root --> Agents["Agent Schemas x4<br/>names, overrides, sisyphus..."]
Root --> Tasks["Task Schemas x2<br/>background-task, babysitting"]
Root --> Categories["categories.ts"]
Root --> Hooks["hooks.ts - 41 hook names"]
Root --> Skills["skills.ts"]
Root --> Commands["commands.ts"]
Root --> CC["claude-code.ts"]
Root --> Exp["experimental.ts"]
Root --> Tmux["tmux.ts"]
Root --> Other["notification, git-master<br/>browser, websearch..."]
总 schema 结构:
📁 文件说明:
src/config/schema/oh-my-opencode-config.ts汇总 22 个子域的总 schema。
graph TD
Config["Root Config"]
Config --> Disable["Global Disable Lists"]
Disable --> D1["disabled_mcps"]
Disable --> D2["disabled_agents"]
Disable --> D3["disabled_skills"]
Disable --> D4["disabled_hooks"]
Disable --> D5["disabled_commands"]
Config --> Nested["Nested Sub-configs"]
Nested --> N1["agents"]
Nested --> N2["categories"]
Nested --> N3["claude_code"]
Nested --> N4["skills"]
Nested --> N5["experimental"]
Config --> Infra["Infrastructure"]
Infra --> I1["background_task"]
Infra --> I2["notification"]
Infra --> I3["git_master"]
Infra --> I4["tmux"]
JSONC 支持
配置支持 JSONC(JSON with Comments)——几十个开关的文件如果不能写注释,几个月后就忘了每个配置是什么意思。
{
// Disable Atlas (not needed for this project)
"disabled_agents": ["atlas"],
// Limit concurrency (API quota limited)
"background_task": {
"defaultConcurrency": 3
}
}
注释就是文档。OMO 通过 parseJsonc() 解析,优先查找 .jsonc 后缀。
部分回退(Partial Fallback)
💡 CS 术语:不是整个系统退回默认,而是只让出问题的部分降级。
flowchart TD
Load["Read Config File"] --> Full["safeParse() - Full Validation"]
Full --> OK{All Valid?}
OK -->|Yes| Use["Use Full Config"]
OK -->|No| Log["Log Error"]
Log --> Partial["parseConfigPartially()"]
Partial --> S1{agents OK?}
S1 -->|Yes| K1["Keep agents"]
S1 -->|No| SK1["Skip, use defaults"]
Partial --> S2{hooks OK?}
S2 -->|Yes| K2["Keep hooks"]
S2 -->|No| SK2["Skip, use defaults"]
Partial --> S3{experimental OK?}
S3 -->|Yes| K3["Keep experimental"]
S3 -->|No| SK3["Skip, use defaults"]
K1 & SK1 & K2 & SK2 & K3 & SK3 --> Result["Merged Partially-valid Config"]
场景:experimental 里写了过时的字段名。没有部分回退时,整个配置文件无效,精心配置的 agents、hooks 全部丢失。有了部分回退,只跳过坏掉的 experimental,其他照常。
合并逻辑
flowchart TD
subgraph Objects["Object Fields"]
OB["agents, categories, claude_code"]
OB --> DM["deepMerge()<br/>Project overrides specific fields"]
end
subgraph Lists["Disable Lists"]
LS["disabled_agents, disabled_hooks..."]
LS --> SA["Set union + dedup<br/>Both say disable = disabled"]
end
| 字段类型 | 合并方式 | 原因 |
|---|---|---|
| 对象字段 | deepMerge | 项目级只覆盖部分字段 |
| 禁用列表 | Set 去重累加 | 两层都说“不要“→最终“不要“ |
从配置到运行策略
配置不是读完就结束。OMO 把“静态配置“编译成“运行态策略“:
flowchart LR
subgraph Static["Config File"]
S1["tmux: main-vertical"]
S2["disabled_hooks: atlas"]
S3["defaultConcurrency: 3"]
end
subgraph Runtime["Runtime Objects"]
R1["tmuxConfig object<br/>all defaults filled"]
R2["isHookEnabled() fn<br/>one call = answer"]
R3["ConcurrencyManager<br/>initialized with limit=3"]
end
Static -->|"compile"| Runtime
横向合并——跨生态资产:
flowchart LR
S1["Builtin Cmds"] --> M["applyCommandConfig()"]
S2["Skill Cmds"] --> M
S3["CC Cmds"] --> M
S4["OC Cmds"] --> M
S5["Plugin Cmds"] --> M
M --> Final["Merged Command Registry"]
本节要点
- 三层优先级:默认 → 用户级 → 项目级
- 22 个 Schema:按责任边界拆分,类型严格
- JSONC:注释是长期维护的基础设施
- 部分回退:一个段落坏了不拖垮其他
- 禁用列表累加:两层都说“不要“→最终“不要“
- 配置到策略:静态文件被编译成运行态对象