feat: add claude_code config object to toggle Claude Code compatibility features (#23)

This commit is contained in:
Nguyen Quang Huy
2025-12-12 13:23:50 +07:00
committed by GitHub
parent 3eb88aa861
commit 359340de65
5 changed files with 105 additions and 8 deletions

View File

@@ -242,6 +242,32 @@ OpenCode 는 아주 확장가능하고 아주 커스터마이저블합니다.
Oh My OpenCode는 Claude Code 설정과 완벽하게 호환됩니다. Claude Code를 사용하셨다면, 기존 설정을 그대로 사용할 수 있습니다. Oh My OpenCode는 Claude Code 설정과 완벽하게 호환됩니다. Claude Code를 사용하셨다면, 기존 설정을 그대로 사용할 수 있습니다.
#### 호환성 토글
특정 Claude Code 호환 기능을 비활성화하려면 `claude_code` 설정 객체를 사용하세요:
```json
{
"claude_code": {
"mcp": false,
"commands": false,
"skills": false,
"agents": false,
"hooks": false
}
}
```
| 토글 | `false`일 때 로딩 비활성화 경로 | 영향 받지 않음 |
|------|-------------------------------|---------------|
| `mcp` | `~/.claude/.mcp.json`, `./.mcp.json`, `./.claude/.mcp.json` | 내장 MCP (context7, websearch_exa) |
| `commands` | `~/.claude/commands/*.md`, `./.claude/commands/*.md` | `~/.config/opencode/command/`, `./.opencode/command/` |
| `skills` | `~/.claude/skills/*/SKILL.md`, `./.claude/skills/*/SKILL.md` | - |
| `agents` | `~/.claude/agents/*.md`, `./.claude/agents/*.md` | 내장 에이전트 (oracle, librarian 등) |
| `hooks` | `~/.claude/settings.json`, `./.claude/settings.json`, `./.claude/settings.local.json` | - |
모든 토글은 기본값이 `true` (활성화)입니다. 완전한 Claude Code 호환성을 원하면 `claude_code` 객체를 생략하세요.
#### Hooks 통합 #### Hooks 통합
Claude Code의 `settings.json` 훅 시스템을 통해 커스텀 스크립트를 실행합니다. Oh My OpenCode는 다음 위치의 훅을 읽고 실행합니다: Claude Code의 `settings.json` 훅 시스템을 통해 커스텀 스크립트를 실행합니다. Oh My OpenCode는 다음 위치의 훅을 읽고 실행합니다:

View File

@@ -240,6 +240,32 @@ Don't need these? Disable them via `oh-my-opencode.json`:
Oh My OpenCode provides seamless Claude Code configuration compatibility. If you've been using Claude Code, your existing setup works out of the box. Oh My OpenCode provides seamless Claude Code configuration compatibility. If you've been using Claude Code, your existing setup works out of the box.
#### Compatibility Toggles
If you want to disable specific Claude Code compatibility features, use the `claude_code` configuration object:
```json
{
"claude_code": {
"mcp": false,
"commands": false,
"skills": false,
"agents": false,
"hooks": false
}
}
```
| Toggle | When `false`, disables loading from... | NOT affected |
|--------|----------------------------------------|--------------|
| `mcp` | `~/.claude/.mcp.json`, `./.mcp.json`, `./.claude/.mcp.json` | Built-in MCPs (context7, websearch_exa) |
| `commands` | `~/.claude/commands/*.md`, `./.claude/commands/*.md` | `~/.config/opencode/command/`, `./.opencode/command/` |
| `skills` | `~/.claude/skills/*/SKILL.md`, `./.claude/skills/*/SKILL.md` | - |
| `agents` | `~/.claude/agents/*.md`, `./.claude/agents/*.md` | Built-in agents (oracle, librarian, etc.) |
| `hooks` | `~/.claude/settings.json`, `./.claude/settings.json`, `./.claude/settings.local.json` | - |
All toggles default to `true` (enabled). Omit the entire `claude_code` object for full Claude Code compatibility.
#### Hooks Integration #### Hooks Integration
Execute custom scripts via Claude Code's `settings.json` hook system. Oh My OpenCode reads and executes hooks defined in: Execute custom scripts via Claude Code's `settings.json` hook system. Oh My OpenCode reads and executes hooks defined in:

View File

@@ -154,6 +154,32 @@
} }
} }
} }
},
"claude_code": {
"type": "object",
"description": "Toggle Claude Code compatibility features on/off. All default to true (enabled).",
"properties": {
"mcp": {
"type": "boolean",
"description": "Load MCP servers from ~/.claude/.mcp.json, ./.mcp.json, ./.claude/.mcp.json"
},
"commands": {
"type": "boolean",
"description": "Load commands from ~/.claude/commands/*.md, ./.claude/commands/*.md"
},
"skills": {
"type": "boolean",
"description": "Load skills from ~/.claude/skills/*/SKILL.md, ./.claude/skills/*/SKILL.md"
},
"agents": {
"type": "boolean",
"description": "Load agents from ~/.claude/agents/*.md, ./.claude/agents/*.md"
},
"hooks": {
"type": "boolean",
"description": "Execute hooks from ~/.claude/settings.json, ./.claude/settings.json, ./.claude/settings.local.json"
}
}
} }
} }
} }

View File

@@ -42,11 +42,20 @@ export const AgentOverrideConfigSchema = z.object({
export const AgentOverridesSchema = z.record(AgentNameSchema, AgentOverrideConfigSchema) export const AgentOverridesSchema = z.record(AgentNameSchema, AgentOverrideConfigSchema)
export const ClaudeCodeConfigSchema = z.object({
mcp: z.boolean().optional(),
commands: z.boolean().optional(),
skills: z.boolean().optional(),
agents: z.boolean().optional(),
hooks: z.boolean().optional(),
})
export const OhMyOpenCodeConfigSchema = z.object({ export const OhMyOpenCodeConfigSchema = z.object({
$schema: z.string().optional(), $schema: z.string().optional(),
disabled_mcps: z.array(McpNameSchema).optional(), disabled_mcps: z.array(McpNameSchema).optional(),
disabled_agents: z.array(AgentNameSchema).optional(), disabled_agents: z.array(AgentNameSchema).optional(),
agents: AgentOverridesSchema.optional(), agents: AgentOverridesSchema.optional(),
claude_code: ClaudeCodeConfigSchema.optional(),
}) })
export type OhMyOpenCodeConfig = z.infer<typeof OhMyOpenCodeConfigSchema> export type OhMyOpenCodeConfig = z.infer<typeof OhMyOpenCodeConfigSchema>

View File

@@ -101,6 +101,10 @@ function mergeConfigs(
...(override.disabled_mcps ?? []), ...(override.disabled_mcps ?? []),
]), ]),
], ],
claude_code:
override.claude_code !== undefined || base.claude_code !== undefined
? { ...(base.claude_code ?? {}), ...(override.claude_code ?? {}) }
: undefined,
}; };
} }
@@ -132,6 +136,7 @@ function loadPluginConfig(directory: string): OhMyOpenCodeConfig {
agents: config.agents, agents: config.agents,
disabled_agents: config.disabled_agents, disabled_agents: config.disabled_agents,
disabled_mcps: config.disabled_mcps, disabled_mcps: config.disabled_mcps,
claude_code: config.claude_code,
}); });
return config; return config;
} }
@@ -148,7 +153,9 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
const directoryReadmeInjector = createDirectoryReadmeInjectorHook(ctx); const directoryReadmeInjector = createDirectoryReadmeInjectorHook(ctx);
const emptyTaskResponseDetector = createEmptyTaskResponseDetectorHook(ctx); const emptyTaskResponseDetector = createEmptyTaskResponseDetectorHook(ctx);
const thinkMode = createThinkModeHook(); const thinkMode = createThinkModeHook();
const claudeCodeHooks = createClaudeCodeHooksHook(ctx, {}); const claudeCodeHooks = createClaudeCodeHooksHook(ctx, {
disabledHooks: (pluginConfig.claude_code?.hooks ?? true) ? undefined : true,
});
const anthropicAutoCompact = createAnthropicAutoCompactHook(ctx); const anthropicAutoCompact = createAnthropicAutoCompactHook(ctx);
updateTerminalTitle({ sessionId: "main" }); updateTerminalTitle({ sessionId: "main" });
@@ -165,8 +172,9 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
pluginConfig.disabled_agents, pluginConfig.disabled_agents,
pluginConfig.agents, pluginConfig.agents,
); );
const userAgents = loadUserAgents();
const projectAgents = loadProjectAgents(); const userAgents = (pluginConfig.claude_code?.agents ?? true) ? loadUserAgents() : {};
const projectAgents = (pluginConfig.claude_code?.agents ?? true) ? loadProjectAgents() : {};
config.agent = { config.agent = {
...builtinAgents, ...builtinAgents,
@@ -178,20 +186,22 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
...config.tools, ...config.tools,
}; };
const mcpResult = await loadMcpConfigs(); const mcpResult = (pluginConfig.claude_code?.mcp ?? true)
? await loadMcpConfigs()
: { servers: {} };
config.mcp = { config.mcp = {
...config.mcp, ...config.mcp,
...createBuiltinMcps(pluginConfig.disabled_mcps), ...createBuiltinMcps(pluginConfig.disabled_mcps),
...mcpResult.servers, ...mcpResult.servers,
}; };
const userCommands = loadUserCommands(); const userCommands = (pluginConfig.claude_code?.commands ?? true) ? loadUserCommands() : {};
const opencodeGlobalCommands = loadOpencodeGlobalCommands(); const opencodeGlobalCommands = loadOpencodeGlobalCommands();
const systemCommands = config.command ?? {}; const systemCommands = config.command ?? {};
const projectCommands = loadProjectCommands(); const projectCommands = (pluginConfig.claude_code?.commands ?? true) ? loadProjectCommands() : {};
const opencodeProjectCommands = loadOpencodeProjectCommands(); const opencodeProjectCommands = loadOpencodeProjectCommands();
const userSkills = loadUserSkillsAsCommands(); const userSkills = (pluginConfig.claude_code?.skills ?? true) ? loadUserSkillsAsCommands() : {};
const projectSkills = loadProjectSkillsAsCommands(); const projectSkills = (pluginConfig.claude_code?.skills ?? true) ? loadProjectSkillsAsCommands() : {};
config.command = { config.command = {
...userCommands, ...userCommands,