Instead of creating a merged config directory and injecting CLAUDE_CONFIG_DIR on every terminal spawn, place a thin wrapper script at Resources/bin/claude that intercepts claude invocations to inject --session-id and --settings flags. This eliminates blocking I/O on terminal creation and removes config management complexity. - Add Resources/bin/claude wrapper script with hook injection - Add shell integration PATH fix (re-prepend after .zshrc/.bashrc) - Add transcript reading for richer stop notifications - Add set_status/clear_status to notifications socket allowlist - Add Settings toggle to disable Claude Code integration - Update docs to reflect automatic integration approach - Unset CLAUDECODE env var to avoid nested session detection
41 lines
1.9 KiB
Bash
Executable file
41 lines
1.9 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# cmux claude wrapper - injects hooks and session tracking
|
|
#
|
|
# When running inside a cmux terminal (CMUX_SURFACE_ID is set), this wrapper
|
|
# intercepts `claude` invocations to inject --session-id and --settings flags
|
|
# so that Claude Code hooks fire back into cmux for notifications/status.
|
|
# Outside cmux, it passes through to the real claude binary unchanged.
|
|
|
|
# Find the real claude binary, skipping our own directory.
|
|
find_real_claude() {
|
|
local self_dir
|
|
self_dir="$(cd "$(dirname "$0")" && pwd)"
|
|
local IFS=:
|
|
for d in $PATH; do
|
|
[[ "$d" == "$self_dir" ]] && continue
|
|
[[ -x "$d/claude" ]] && printf '%s' "$d/claude" && return 0
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# Pass through if not in a cmux terminal or hooks are disabled.
|
|
if [[ -z "$CMUX_SURFACE_ID" || "$CMUX_CLAUDE_HOOKS_DISABLED" == "1" ]]; then
|
|
REAL_CLAUDE="$(find_real_claude)" || { echo "Error: claude not found in PATH" >&2; exit 127; }
|
|
exec "$REAL_CLAUDE" "$@"
|
|
fi
|
|
|
|
# Find real claude.
|
|
REAL_CLAUDE="$(find_real_claude)" || { echo "Error: claude not found in PATH" >&2; exit 127; }
|
|
|
|
# Unset CLAUDECODE to avoid "nested session" detection — cmux terminals are
|
|
# independent sessions even when the parent shell was launched from Claude Code.
|
|
unset CLAUDECODE
|
|
|
|
# Generate a fresh session ID for this invocation.
|
|
SESSION_ID="$(uuidgen | tr '[:upper:]' '[:lower:]')"
|
|
|
|
# Build hooks settings JSON.
|
|
# Claude Code merges --settings additively with the user's own settings.json.
|
|
HOOKS_JSON='{"hooks":{"SessionStart":[{"matcher":"","hooks":[{"type":"command","command":"cmux claude-hook session-start","timeout":10}]}],"Stop":[{"matcher":"","hooks":[{"type":"command","command":"cmux claude-hook stop","timeout":10}]}],"Notification":[{"matcher":"","hooks":[{"type":"command","command":"cmux claude-hook notification","timeout":10}]}]}}'
|
|
|
|
exec "$REAL_CLAUDE" --session-id "$SESSION_ID" --settings "$HOOKS_JSON" "$@"
|