OpenCode supports a hooks feature similar to Claude Code, but with a plugin-based architecture that offers more flexibility and programmability.
| Feature | Claude Code | OpenCode |
|---|---|---|
| Primary approach | Config-based shell commands | Plugin-based TypeScript/JS |
| Hook execution | Bash scripts via JSON config | Full SDK access in plugins |
| Config hooks | Main feature | Experimental feature |
OpenCode uses a plugin architecture for hooks defined in TypeScript/JavaScript. Plugins have access to the full SDK client and context.
| Hook | Description |
|---|---|
event |
Subscribe to events (file changes, session events, etc.) |
config |
Modify configuration |
tool |
Define custom tools |
auth |
Custom authentication |
chat.message |
Intercept chat messages |
chat.params |
Modify chat parameters |
permission.ask |
Handle permission requests |
tool.execute.before |
Run before tool execution |
tool.execute.after |
Run after tool execution |
experimental.chat.messages.transform |
Transform messages |
experimental.chat.system.transform |
Transform system prompts |
experimental.session.compacting |
Handle session compaction |
OpenCode provides a rich event system that plugins can subscribe to:
- File Events:
file.edited,file.watcher.updated - Session Events:
session.created,session.compacted,session.deleted,session.idle,session.status,session.updated - Message Events:
message.part.removed,message.part.updated,message.removed,message.updated - Tool Events:
tool.execute.after,tool.execute.before - Permission Events:
permission.replied,permission.updated - LSP Events:
lsp.client.diagnostics,lsp.updated - Command Events:
command.executed
- Project plugins:
.opencode/plugin/ - Global plugins:
~/.config/opencode/plugin/ - npm plugins: Configured in
opencode.jsonviapluginarray
OpenCode also has experimental config-based hooks in opencode.json that are more similar to Claude Code's approach:
{
"experimental": {
"hook": {
"file_edited": {
"*.ts": [
{
"command": ["prettier", "--write"],
"environment": { "NODE_ENV": "development" }
}
]
},
"session_completed": [
{
"command": ["notify-send", "Session completed!"]
}
]
}
}
}file_edited- Run commands when files matching a pattern are editedsession_completed- Run commands when a session completes
Here's an example of a plugin that protects .env files from being read:
import type { Plugin } from "@anthropic-ai/opencode-plugin"
export default {
"tool.execute.before": async (input, output) => {
if (input.call.name === "Read" && input.call.input.file_path?.includes(".env")) {
output.abort = "Cannot read .env files for security reasons"
}
}
} satisfies Plugin["hooks"]- Configured in JSON settings files
- Execute shell commands
- Events:
PreToolUse,PostToolUse,Stop,SubagentStop,Notification,UserPromptSubmit,PreCompact,SessionStart,SessionEnd - Hooks receive JSON input via stdin and return exit codes or JSON output
- Plugin-based with TypeScript/JavaScript
- Full programmatic access to SDK and context
- More experimental hooks for transforming messages and system prompts
- Config-based hooks are experimental and limited to
file_editedandsession_completed