mirror of
https://github.com/alexbelgium/hassio-addons.git
synced 2026-08-28 15:53:32 +02:00
Version 1.25 chowned the data location to a hardcoded 1000:1000 but never mapped the shared abc desktop user to that UID: during cont-init abc was still the image default (911), so TokenSave, RTK, nginx, PulseAudio, the Mesa shader cache, and Claude Desktop itself failed with Permission denied. The base image's init-adduser then remapped abc to root mid-startup because it reads PUID/PGID from add-on options (fallback 0) where they were never defined, which additionally made Claude Code reject bypass mode. - Add PUID/PGID add-on options (default 1000:1000) and remap abc to that identity at the top of 20-folders.sh, before any ownership pass and before any service resolves the user; pin init-adduser to the same effective identity so it cannot diverge mid-startup. - In permission_mode bypass, fall back from a configured PUID 0 to UID 1000, since Claude Code refuses bypass permissions as root. - Replace the nonexistent bashio::config.array (only present in the repo's standalone bashio) with bashio::config in the TokenSave repository setup, tools configuration, and claude-tools-doctor.sh. - Chown managed Claude configuration files to the effective abc identity instead of the raw configured PUID/PGID, which fell back to root. - Pre-create /tmp/.X11-unix (sticky 1777) so Xorg running as non-root abc on the tmpfs /tmp can create its socket. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KN8i26JrKSaBdvTrpVEyQ6
95 lines
3.0 KiB
Bash
Executable File
95 lines
3.0 KiB
Bash
Executable File
#!/usr/bin/with-contenv bashio
|
|
# shellcheck shell=bash
|
|
set -e
|
|
set -o pipefail
|
|
|
|
# 20-folders.sh already remapped abc to the effective runtime identity (never root in bypass
|
|
# mode), so follow abc instead of re-reading the raw PUID/PGID options here.
|
|
RUNTIME_UID="$(id -u abc)"
|
|
RUNTIME_GID="$(id -g abc)"
|
|
PERMISSION_MODE="$(bashio::config 'permission_mode')"
|
|
SETTINGS_PATH="$HOME/.claude/settings.json"
|
|
STATE_PATH="$HOME/.claude/.addon-permission-mode.json"
|
|
|
|
case "$PERMISSION_MODE" in
|
|
strict|auto|bypass) ;;
|
|
*)
|
|
bashio::log.warning "Unknown permission_mode '${PERMISSION_MODE}'; falling back to strict"
|
|
PERMISSION_MODE="strict"
|
|
;;
|
|
esac
|
|
|
|
mkdir -p "$(dirname "$SETTINGS_PATH")"
|
|
PERMISSION_MODE="$PERMISSION_MODE" SETTINGS_PATH="$SETTINGS_PATH" STATE_PATH="$STATE_PATH" python3 - <<'PY'
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
|
|
mode = os.environ["PERMISSION_MODE"]
|
|
settings_path = Path(os.environ["SETTINGS_PATH"])
|
|
state_path = Path(os.environ["STATE_PATH"])
|
|
|
|
try:
|
|
settings = json.loads(settings_path.read_text()) if settings_path.exists() else {}
|
|
except (OSError, json.JSONDecodeError):
|
|
if settings_path.exists():
|
|
settings_path.rename(settings_path.with_suffix(settings_path.suffix + ".bak"))
|
|
settings = {}
|
|
if not isinstance(settings, dict):
|
|
settings = {}
|
|
|
|
try:
|
|
state = json.loads(state_path.read_text()) if state_path.exists() else None
|
|
except (OSError, json.JSONDecodeError):
|
|
state = None
|
|
if not isinstance(state, dict):
|
|
state = None
|
|
|
|
permissions = settings.get("permissions")
|
|
if not isinstance(permissions, dict):
|
|
permissions = {}
|
|
|
|
if mode == "strict":
|
|
# Restore the value that existed before the add-on first managed this setting.
|
|
if state is not None:
|
|
if state.get("previous_exists"):
|
|
permissions["defaultMode"] = state.get("previous_value")
|
|
else:
|
|
permissions.pop("defaultMode", None)
|
|
state_path.unlink(missing_ok=True)
|
|
else:
|
|
if state is None:
|
|
state = {
|
|
"previous_exists": "defaultMode" in permissions,
|
|
"previous_value": permissions.get("defaultMode"),
|
|
}
|
|
state_path.write_text(json.dumps(state, indent=2) + "\n")
|
|
state_path.chmod(0o600)
|
|
permissions["defaultMode"] = "auto" if mode == "auto" else "bypassPermissions"
|
|
|
|
if permissions:
|
|
settings["permissions"] = permissions
|
|
else:
|
|
settings.pop("permissions", None)
|
|
|
|
settings_path.write_text(json.dumps(settings, indent=2) + "\n")
|
|
settings_path.chmod(0o600)
|
|
PY
|
|
|
|
case "$PERMISSION_MODE" in
|
|
strict)
|
|
bashio::log.info "Claude Code permission mode: strict (normal prompts)"
|
|
;;
|
|
auto)
|
|
bashio::log.info "Claude Code permission mode: auto (safe actions approved automatically)"
|
|
;;
|
|
bypass)
|
|
bashio::log.warning "Claude Code permission mode: bypass (permission checks disabled for mounted data and available tools)"
|
|
;;
|
|
esac
|
|
|
|
chown -- "${RUNTIME_UID}:${RUNTIME_GID}" "$SETTINGS_PATH" 2> /dev/null || true
|
|
if [ -e "$STATE_PATH" ]; then
|
|
chown -- "${RUNTIME_UID}:${RUNTIME_GID}" "$STATE_PATH" 2> /dev/null || true
|
|
fi
|