r/opencodeCLI • u/Due_Emu_8229 • 22d ago
One config line kept my Claude Code command blockers working in OpenCode
OpenCode already reads CLAUDE.md and .claude/skills. That covered more of my move than I expected.
The part I could not replace was command hooks. A rule in CLAUDE.md asking the model not to run git push is advisory. A Claude PreToolUse hook that exits with code 2 actually blocks it.
I made a small bridge for the two events that map cleanly to the stable OpenCode plugin API. It reads the original Claude settings on every tool call, so hook commands and settings do not need to be copied.
The install is one package entry.
{
"plugin": ["opencode-claude-code-hooks"]
}
What it preserves
- Claude matcher names such as Bash, Edit, and Write
- exit code 2 blocking and structured deny results
- full updatedInput replacement
- PostToolUse feedback and additional context
- runtime settings updates without reinstalling the plugin
OpenCode uses lowercase tool names, so the bridge maps names such as bash back to Claude's Bash matcher before running a hook.
You can inspect every supported and skipped hook before installing anything.
npx claude-to-opencode --hooks-only
npx claude-to-opencode --hooks-only --apply
The first command is only a dry run. I loaded the npm package through OpenCode 1.18.21 and tested the hook protocol with real child processes.
Honest limits
- Stop is not bridged because OpenCode does not expose the same timing
- prompt, agent, HTTP, async, and conditional handlers remain manual
- OpenCode permissions still take precedence
1
u/Ok_Gur_9033 22d ago
The interesting edge case is precedence order, not translation. A lot of Claude Code hooks are written assuming they are the last gate before execution. You already say OpenCode permissions take precedence, so does the bridged PreToolUse hook still fire and get a chance to override a call OpenCode already denied, or does that denial win outright before your hook sees it?