Hooks are probably hidden gems for a client/server architecture CLI like opencode. It's bit different that the current event system hooks in that we can inject other behaviors (like inline linting) or pass messages to a UI framework.
Claude Code has these hooks:
• PreToolUse: runs before a tool is called; can block or modify tool execution (e.g., validate or restrict commands).
• PostToolUse: runs after a tool completes successfully; can provide feedback or take actions based on tool results.
• Notification: runs when Claude Code sends notifications (e.g., when awaiting input or permission).
• Stop: runs when Claude Code finishes responding; can block or allow the session to end.
Maybe a middle ground we can take advantage of for /share as well, as the websocket sends some simple key values:
// Initial message (just created)
{ "key": "session/message/abc/msg1", "content": { "parts": [],
"metadata": {...} }}
// After text starts streaming
{ "key": "session/message/abc/msg1", "content": { "parts": [{"type":
"text", "text": "I'll help..."}], "metadata": {...} }}
// After tool call starts
{ "key": "session/message/abc/msg1", "content": { "parts": [..., {"type":
"tool-invocation", "state": "partial-call"}], "metadata": {...} }}
// After tool completes
{ "key": "session/message/abc/msg1", "content": { "parts": [..., {"type":
"tool-invocation", "state": "result", "result": "..."}], "metadata":
{"tool": {"call_123": {"time": {...}}}} }}
Hooks are probably hidden gems for a client/server architecture CLI like opencode. It's bit different that the current event system hooks in that we can inject other behaviors (like inline linting) or pass messages to a UI framework.
Claude Code has these hooks:
•
PreToolUse: runs before a tool is called; can block or modify tool execution (e.g., validate or restrict commands).•
PostToolUse: runs after a tool completes successfully; can provide feedback or take actions based on tool results.•
Notification: runs when Claude Code sends notifications (e.g., when awaiting input or permission).•
Stop: runs when Claude Code finishes responding; can block or allow the session to end.Maybe a middle ground we can take advantage of for
/shareas well, as the websocket sends some simple key values: