Python SDK
Installation
pip install openhookConsuming Events (Hook Side)
from openhook import parse_stdin, is_openhook, from_legacy
import json, sys
payload = json.loads(sys.stdin.read())
if is_openhook(payload): event = OpenHookEvent.from_dict(payload)else: event = from_legacy(payload) # backward compat
print(event.source) # "claude-code"print(event.type) # EventType.SESSION_ENDprint(event.transcript_path) # Path("/path/to/session.jsonl") or Noneprint(event.is_trace) # True if transcript_path existsProducing Events (Tool Side)
from openhook import OpenHookEvent, EventType
event = OpenHookEvent.create( source="my-tool", type=EventType.SESSION_END, session_id="sess_123", data={"transcript_path": "/tmp/session.jsonl", "reason": "completed"},)
# Write to stdout for hook consumptionevent.emit()
# Or serializejson_str = event.to_json()dict_obj = event.to_dict()Validation
from openhook import validate, ValidationError
try: validate({"openhook": "0.1", "type": "session.end"})except ValidationError as e: print(e) # "Missing required fields: id, session_id, source, time"Legacy Compatibility
Convert payloads from tools that don’t yet support OpenHook:
from openhook import from_legacy
# Claude Code legacy formatevent = from_legacy({"sessionId": "abc", "transcriptPath": "/t.jsonl"})assert event.source == "unknown" # auto-detected when possibleassert event.transcript_path is not None
# Copilot legacy formatevent = from_legacy({"hook_event_name": "postToolUse", "session_id": "s1", "tool_name": "Bash"})assert event.type == EventType.TOOL_END