mirror of
https://github.com/alexbelgium/hassio-addons.git
synced 2026-08-16 18:12:29 +02:00
Merge pull request #2870 from alexbelgium/fix/headroom-hf-home-and-bashrc-home-dedup
fix(claude_desktop): repair Headroom MCP model cache, HOME dedup, gitconfig ownership
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
## 1.28 (16-07-2026)
|
||||
- Minor bugs fixed
|
||||
## 1.29 (16-07-2026)
|
||||
|
||||
- Point the Headroom MCP server at the persistent Kompress model cache. 1.27 set `HF_HOME` on the `svc-headroom` proxy longrun only, but the MCP server is a separate process spawned by Claude Desktop / Claude Code from the registered `mcpServers` entry, so it never inherited that export and kept resolving the HuggingFace cache to `~/.cache` — symlinked to tmpfs here and wiped on every restart. Its Kompress ML path therefore never found the model, re-downloaded ~270 MB into tmpfs on each boot, and lost it again on the next one; `headroom_compress` fell back to `router:noop` (unchanged output) on prose and other unstructured content. The managed `headroom` entry in both `claude_desktop_config.json` and `~/.claude.json` now carries `env.HF_HOME` pointing at the same `~/.headroom/hf` cache the proxy warms. Rule-based compression (SmartCrusher, structured tool output) was unaffected and worked throughout.
|
||||
- Fix `~/.gitconfig` being written as `root` and left unreadable by the `abc` runtime user, which broke git for the user that actually runs it: every commit failed with `Author identity unknown` and the `gh` credential helper was invisible to authenticated pushes. `git config --global` ran as root during init and rewrites the file on every start, so `20-folders.sh`'s earlier recursive chown never stuck to it (`.config/gh` survived abc-owned only because the "already authenticated" branch skips rewriting it). The git/gh setup now runs as `abc` via `s6-setuidgid`, matching `81-tokensave_repositories.sh`, and reclaims any root-owned copies left by an earlier version before writing.
|
||||
- Fix `~/.bashrc` accumulating stale `HOME`/`FM_HOME` exports when `data_location` changes. The idempotency guard only tested for the *current* `$LOCATION`, so changing the option and later changing it back appended a second block while leaving the first, and the last one written won for every interactive shell — leaving `$HOME` pointing at a directory the add-on no longer manages. Any tool that resolves config through `$HOME` then read the wrong path (`headroom doctor` reported `claude: not routed (no ~/.claude/settings.json)` against a correctly routed install, and bare `headroom` invocations created a stray `.headroom` tree under the old location). The block is now marker-delimited and rewritten from scratch on every boot, so it is idempotent across any number of `data_location` changes.
|
||||
|
||||
## 1.27 (15-07-2026)
|
||||
|
||||
- Route Claude Desktop cowork/local-agent-mode sessions through the Headroom proxy. Desktop spawns its bundled Claude Code binary at an absolute path (bypassing the add-on's PATH wrapper) with `ANTHROPIC_BASE_URL` pinned to the production endpoint, so those sessions never produced proxy savings. The add-on now manages `env.ANTHROPIC_BASE_URL` in `~/.claude/settings.json` — settings `env` entries replace inherited environment values at CLI startup — gated on `headroom_wrap_claude_code` and never overwriting a user-customized endpoint.
|
||||
|
||||
@@ -109,5 +109,5 @@ slug: claude_desktop
|
||||
tmpfs: true
|
||||
udev: true
|
||||
url: https://github.com/alexbelgium/hassio-addons
|
||||
version: "1.28"
|
||||
version: "1.29"
|
||||
video: true
|
||||
|
||||
@@ -85,10 +85,23 @@ printf "%s" "$LOCATION" > "$S6_ENVDIR/HOME"
|
||||
printf "%s" "$LOCATION" > "$S6_ENVDIR/FM_HOME"
|
||||
printf "%s" "/tmp/cache" > "$S6_ENVDIR/XDG_CACHE_HOME"
|
||||
printf "%s" "$XDG_RUNTIME_DIR" > "$S6_ENVDIR/XDG_RUNTIME_DIR"
|
||||
grep -qxF "export HOME=\"$LOCATION\"" ~/.bashrc 2>/dev/null || {
|
||||
# Re-derived on every boot rather than gated on a "does it already say $LOCATION" grep: that
|
||||
# guard only ever recognized the CURRENT $LOCATION, so a user who changed data_location and
|
||||
# later changed it back left two stale HOME/FM_HOME exports in ~/.bashrc, with the last one
|
||||
# (not necessarily the correct one) winning for every interactive shell. The marker makes this
|
||||
# idempotent regardless of how many times $LOCATION has changed: strip any previously managed
|
||||
# block, then append one that reflects the current value.
|
||||
BASHRC_HOME_BEGIN="# --- BEGIN ADDON HOME (managed) ---"
|
||||
BASHRC_HOME_END="# --- END ADDON HOME (managed) ---"
|
||||
if [ -f ~/.bashrc ]; then
|
||||
sed -i "/^${BASHRC_HOME_BEGIN}\$/,/^${BASHRC_HOME_END}\$/d" ~/.bashrc
|
||||
fi
|
||||
{
|
||||
printf "%s\n" "$BASHRC_HOME_BEGIN"
|
||||
printf "%s\n" "export HOME=\"$LOCATION\""
|
||||
printf "%s\n" "export FM_HOME=\"$LOCATION\""
|
||||
printf "%s\n" "export XDG_CACHE_HOME=\"/tmp/cache\""
|
||||
printf "%s\n" "$BASHRC_HOME_END"
|
||||
} >> ~/.bashrc
|
||||
|
||||
bashio::log.info "Creating $LOCATION"
|
||||
|
||||
@@ -76,6 +76,7 @@ if bashio::config.true 'enable_ha_mcp'; then
|
||||
fi
|
||||
|
||||
HEADROOM_ENABLED="$HEADROOM_ENABLED" HEADROOM_BIN="$(command -v headroom || echo headroom)" \
|
||||
HEADROOM_HF_HOME="${HOME}/.headroom/hf" \
|
||||
TOKENSAVE_ENABLED="$TOKENSAVE_ENABLED" TOKENSAVE_BIN="$(command -v tokensave || echo tokensave)" \
|
||||
HA_MCP_ENABLED="$HA_MCP_ENABLED" HA_MCP_URL="$HA_MCP_URL" HA_MCP_TOKEN="$HA_MCP_TOKEN" \
|
||||
MCP_PROXY_BIN="$(command -v mcp-proxy || echo mcp-proxy)" \
|
||||
@@ -96,6 +97,11 @@ if os.environ["HEADROOM_ENABLED"] == "true":
|
||||
desired["headroom"] = {
|
||||
"command": os.environ["HEADROOM_BIN"],
|
||||
"args": ["mcp", "serve", "--proxy-url", "http://127.0.0.1:8787"],
|
||||
# The MCP server is a separate process from the svc-headroom proxy longrun and does
|
||||
# not inherit its HF_HOME export, so Kompress falls back to the default (tmpfs, wiped
|
||||
# every restart) cache dir, never finds the model, and silently no-ops every
|
||||
# compression request. Point it at the same persistent cache the proxy warms.
|
||||
"env": {"HF_HOME": os.environ["HEADROOM_HF_HOME"]},
|
||||
}
|
||||
if os.environ["TOKENSAVE_ENABLED"] == "true":
|
||||
desired["tokensave"] = {"command": os.environ["TOKENSAVE_BIN"], "args": ["serve"]}
|
||||
|
||||
@@ -17,25 +17,54 @@ if ! command -v gh > /dev/null 2>&1; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Everything below writes into the abc runtime user's HOME, so it must run AS abc. cont-init
|
||||
# runs as root with HOME already pointing at the persistent data location, so plain
|
||||
# `git config --global` recreated ~/.gitconfig owned by root:root on every start — and because
|
||||
# that file is rewritten each boot, 20-folders.sh's earlier recursive chown never stuck to it.
|
||||
# The user who actually runs git, gh and Claude was then unable to read its own committer
|
||||
# identity or the gh credential helper, so every commit failed with "Author identity unknown"
|
||||
# and authenticated pushes fell back to prompting. 20-folders.sh already remapped abc to the
|
||||
# effective runtime identity (never root in bypass mode), so follow abc rather than re-reading
|
||||
# the raw PUID/PGID options here.
|
||||
RUNTIME_UID="$(id -u abc)"
|
||||
RUNTIME_GID="$(id -g abc)"
|
||||
|
||||
run_as_runtime_user() {
|
||||
s6-setuidgid abc env HOME="$HOME" "$@"
|
||||
}
|
||||
|
||||
# Reclaim any root-owned copies left by an earlier add-on version before writing as abc:
|
||||
# these paths are not covered by 82-claude_tools.sh's ownership pass, and a root-owned
|
||||
# ~/.gitconfig would make the first `git config` below fail outright under `set -e`.
|
||||
|
||||
mkdir -p "$HOME/.config"
|
||||
chown -- "${RUNTIME_UID}:${RUNTIME_GID}" "$HOME/.config"
|
||||
|
||||
for managed_path in "$HOME/.gitconfig" "$HOME/.config/gh"; do
|
||||
if [ -e "$managed_path" ]; then
|
||||
chown -R -- "${RUNTIME_UID}:${RUNTIME_GID}" "$managed_path" || bashio::log.warning "Unable to set ownership on $managed_path"
|
||||
fi
|
||||
done
|
||||
|
||||
if bashio::config.has_value 'github_username'; then
|
||||
git config --global user.name "$(bashio::config 'github_username')"
|
||||
run_as_runtime_user git config --global user.name "$(bashio::config 'github_username')"
|
||||
fi
|
||||
|
||||
if bashio::config.has_value 'github_email'; then
|
||||
git config --global user.email "$(bashio::config 'github_email')"
|
||||
run_as_runtime_user git config --global user.email "$(bashio::config 'github_email')"
|
||||
fi
|
||||
|
||||
if bashio::config.has_value 'github_token'; then
|
||||
token="$(bashio::config 'github_token')"
|
||||
mkdir -p "$HOME/.config/gh"
|
||||
chmod 700 "$HOME/.config/gh"
|
||||
if env -u GH_TOKEN -u GITHUB_TOKEN gh auth status --hostname github.com > /dev/null 2>&1; then
|
||||
run_as_runtime_user mkdir -p "$HOME/.config/gh"
|
||||
run_as_runtime_user chmod 700 "$HOME/.config/gh"
|
||||
if run_as_runtime_user env -u GH_TOKEN -u GITHUB_TOKEN gh auth status --hostname github.com > /dev/null 2>&1; then
|
||||
bashio::log.info "GitHub CLI already authenticated for github.com"
|
||||
else
|
||||
bashio::log.info "Configuring GitHub CLI authentication for github.com"
|
||||
printf '%s\n' "$token" | env -u GH_TOKEN -u GITHUB_TOKEN gh auth login --hostname github.com --with-token || bashio::log.warning "GitHub CLI authentication failed"
|
||||
printf '%s\n' "$token" | run_as_runtime_user env -u GH_TOKEN -u GITHUB_TOKEN gh auth login --hostname github.com --with-token || bashio::log.warning "GitHub CLI authentication failed"
|
||||
fi
|
||||
env -u GH_TOKEN -u GITHUB_TOKEN gh auth setup-git --hostname github.com || bashio::log.warning "GitHub CLI git credential setup failed"
|
||||
run_as_runtime_user env -u GH_TOKEN -u GITHUB_TOKEN gh auth setup-git --hostname github.com || bashio::log.warning "GitHub CLI git credential setup failed"
|
||||
else
|
||||
bashio::log.info "GitHub CLI available. Set github_token to authenticate gh and git operations."
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user