#!/usr/bin/with-contenv bashio # shellcheck shell=bash set -o pipefail REAL_CLAUDE="/usr/bin/claude" HEADROOM_BIN="$(command -v headroom || true)" HEADROOM_URL="http://127.0.0.1:8787" PERMISSION_MODE="$(bashio::config 'permission_mode')" declare -a CLAUDE_PERMISSION_ARGS=() case "$PERMISSION_MODE" in bypass) CLAUDE_PERMISSION_ARGS+=("--dangerously-skip-permissions") ;; auto) CLAUDE_PERMISSION_ARGS+=("--permission-mode" "auto") ;; strict|"") ;; *) echo "claude wrapper: unknown permission_mode '${PERMISSION_MODE}', using strict mode" >&2 ;; esac if [ ! -x "$REAL_CLAUDE" ]; then echo "claude wrapper: ${REAL_CLAUDE} is unavailable" >&2 exit 127 fi # Claude Code rejects bypass mode when the effective UID is 0. Normal Desktop sessions run # as abc, which startup remaps to a non-root UID when bypass is selected. Also handle a user # invoking this wrapper directly from a root container console by dropping to abc here. if [ "$PERMISSION_MODE" = "bypass" ] && [ "$(id -u)" -eq 0 ]; then if command -v s6-setuidgid > /dev/null 2>&1 && [ "$(id -u abc)" -ne 0 ]; then exec s6-setuidgid abc "$0" "$@" fi echo "claude wrapper: bypass mode requires a non-root runtime user, but abc is still UID 0" >&2 exit 1 fi if bashio::config.true 'install_headroom' && bashio::config.true 'headroom_wrap_claude_code'; then if [ -x "$HEADROOM_BIN" ] && curl -fsS --max-time 2 "${HEADROOM_URL}/health" > /dev/null 2>&1; then # Put /usr/bin before /usr/local/bin while Headroom resolves its upstream `claude` # executable; otherwise it would resolve this wrapper recursively. export HEADROOM_CONTEXT_TOOL="rtk" exec env PATH="/usr/bin:/bin:/usr/local/bin" \ "$HEADROOM_BIN" wrap claude --no-proxy -- \ "${CLAUDE_PERMISSION_ARGS[@]}" "$@" fi echo "claude wrapper: Headroom proxy is unavailable; launching Claude Code directly" >&2 fi exec "$REAL_CLAUDE" "${CLAUDE_PERMISSION_ARGS[@]}" "$@"