Claude Code Hooks & IPC
Relevant source files
The following files were used as context for generating this wiki page:
The Claude Code Hooks and Inter-Process Communication (IPC) system forms the backbone of Buddi's integration with Anthropic's Claude Code CLI. This system allows Buddi to monitor live sessions, track tool usage, and provide a graphical interface for permission approvals. By intercepting lifecycle events from the CLI, Buddi can synchronize its internal state and buddy animations with the actual operations performed by the AI agent.
The architecture relies on a Python-based hook script registered within the Claude Code configuration, which communicates with the main Swift application via a Unix domain socket. This setup enables bidirectional communication: the CLI pushes event updates to Buddi, and Buddi can return user decisions (such as tool approval or denial) back to the CLI in real-time.
Sources: README.md:5-15, buddi/Buddi/Resources/buddi-hook.py:1-12
System Architecture
The integration follows a linear data flow from the terminal-based CLI to the macOS notch UI. The system is composed of four primary layers: the Claude Code CLI, the Python Hook Script, the Unix Domain Socket, and the Buddi Swift backend.
The diagram above illustrates the bidirectional flow required for synchronous events like permission requests.
Sources: README.md:46-50, buddi/Buddi/Resources/buddi-hook.py:84-110
Hook Installation & Lifecycle
Buddi automates the setup process by installing a Python script into the user's local Claude configuration directory.
Automatic Setup
The HookInstaller is responsible for deploying the buddi-hook.py script to ~/.claude/hooks/ and modifying the ~/.claude/settings.json file. It injects a "command" type hook for various event triggers, ensuring that the CLI invokes the Buddi script whenever specific actions occur.
| Event Name | Configuration Type | Logic |
|---|---|---|
UserPromptSubmit | Without Matcher | Triggered when user sends a message. |
PreToolUse | With Matcher (*) | Triggered before a tool is executed. |
PermissionRequest | With Matcher & Timeout | Triggered when Claude needs authorization. |
SessionStart / End | Without Matcher | Handles session lifecycle state. |
PreCompact | Config Matcher | Handles context window compaction. |
Sources: buddi/Buddi/Services/Hooks/HookInstaller.swift:14-38, buddi/Buddi/Services/Hooks/HookInstaller.swift:55-68
The Python Hook Script (buddi-hook.py)
This script acts as the bridge. It reads JSON event data from stdin, gathers environmental context (like the parent PID, TTY, or cmux surface information), and forwards this metadata to the Unix socket.
For asynchronous events (like PreToolUse), it is a "fire and forget" operation. For synchronous events (PermissionRequest), the script blocks and waits for a response from the socket before exiting with a JSON payload that Claude Code interprets as an approval or denial.
Sources: buddi/Buddi/Resources/buddi-hook.py:126-155, buddi/Buddi/Resources/buddi-hook.py:175-188
IPC Communication via Unix Socket
The communication layer uses a Unix domain socket located at /tmp/buddi.sock.
HookSocketServer
The HookSocketServer in the Swift application listens for incoming connections using GCD DispatchSource. It handles the parsing of HookEvent objects and manages PendingPermission states.
- Socket Path:
/tmp/buddi.sock - Protocol: JSON-encoded data over a stream socket (
SOCK_STREAM). - Non-blocking I/O: Uses
pollandfcntlwithO_NONBLOCKto ensure the app remains responsive during heavy CLI activity.
Sources: buddi/Buddi/Services/Hooks/HookSocketServer.swift:18-25, buddi/Buddi/Services/Hooks/HookSocketServer.swift:115-135
Tool Correlation & Caching
One technical challenge is that PermissionRequest events in Claude Code do not always include the tool_use_id. Buddi solves this by caching the ID during the PreToolUse event, which occurs immediately prior. The HookSocketServer uses a FIFO queue keyed by a hash of the tool name and serialized input to correlate requests.
Sources: buddi/Buddi/Services/Hooks/HookSocketServer.swift:207-228, buddi/Buddi/Services/Hooks/HookSocketServer.swift:243-255
Permission Approval Flow
When Claude requires permission to run a tool, the system enters a synchronous request-response loop.
Multi-Multiplexer Support
Buddi supports tmux and cmux for interaction. If a user approves a tool via the Buddi UI, the ToolApprovalHandler sends the appropriate keystrokes (e.g., "1" + Enter) to the correct terminal pane using the multiplexer's CLI tools.
| Multiplexer | Interaction Method | Requirements |
|---|---|---|
tmux | tmux send-keys -t <target> -l <keys> | tmux must be in system path. |
cmux | cmux send --workspace <ws> --surface <surf> | Requires "Automation mode" in cmux settings. |
Sources: buddi/Buddi/Services/Tmux/ToolApprovalHandler.swift:55-75, buddi/Buddi/Services/Tmux/ToolApprovalHandler.swift:85-110
Session State Synchronization
The SessionStore is the central actor that transforms raw IPC events into meaningful application state.
- Phase Determination: Events are mapped to
SessionPhase(e.g.,processing,waitingForInput,waitingForApproval). - State Mutation: All state changes flow through the
process()method to ensure thread safety. - UI Updates: The store publishes changes via a Combine
sessionsPublisher, which the Notch UI and Chat View subscribe to.
Sources: buddi/Buddi/Services/State/SessionStore.swift:30-45, buddi/Buddi/Services/State/SessionStore.swift:115-135
Conclusion
The Claude Code Hooks & IPC system provides a robust, low-latency link between the terminal-based AI environment and the macOS desktop. By utilizing standard Unix sockets and automated configuration management, it creates a seamless integration that allows users to monitor and control complex AI subagents without leaving the GUI, while maintaining the flexibility of the command-line interface.