mirror of
https://github.com/alexbelgium/hassio-addons.git
synced 2026-09-27 03:43:59 +02:00
Merge pull request #2827 from alexbelgium/claude/desktop-headroom-wrap-fix-r4qaqe
claude_desktop: don't wrap desktop launch with invalid headroom command
This commit is contained in:
@@ -1,3 +1,8 @@
|
|||||||
|
## 1.6 (07-07-2026)
|
||||||
|
|
||||||
|
- Fix default desktop launch failing when `install_headroom` is enabled (the default): the code rewrote the launch to `headroom wrap claude-desktop …`, but `headroom wrap` only supports coding-agent CLIs (`claude`, `codex`, ...) with arguments after `--`, so it produced an invalid command that left the app unlaunched. Leave the plain launch intact and instead register the `headroom` MCP server (`headroom mcp serve`) in Claude Desktop's config, exposing the `headroom_compress`/`headroom_retrieve`/`headroom_stats` tools inside the app. This is the supported headroom integration for Desktop, which overrides `ANTHROPIC_BASE_URL` so transparent proxy compression is not possible ([headroom #869](https://github.com/headroomlabs-ai/headroom/issues/869)). Disabling the option removes the entry again.
|
||||||
|
- Make the autostart resilient: if the launch command fails to start, fall back to the plain Claude Desktop launch so the app always comes up.
|
||||||
|
|
||||||
## 1.5 (07-07-2026)
|
## 1.5 (07-07-2026)
|
||||||
|
|
||||||
- Change the default Claude Desktop data location to `/data/data`.
|
- Change the default Claude Desktop data location to `/data/data`.
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ Claude Desktop sign-in requires a claude.ai plan that supports the Desktop app.
|
|||||||
| `DRINODE` | | Optional GPU device override for Selkies. |
|
| `DRINODE` | | Optional GPU device override for Selkies. |
|
||||||
| `DNS_server` | `8.8.8.8` | DNS server used by the standard DNS module. |
|
| `DNS_server` | `8.8.8.8` | DNS server used by the standard DNS module. |
|
||||||
| `auto_update` | `true` | Check Anthropic's apt repository and upgrade `claude-desktop` at add-on startup. |
|
| `auto_update` | `true` | Check Anthropic's apt repository and upgrade `claude-desktop` at add-on startup. |
|
||||||
| `install_headroom` | `true` | Make the baked-in `headroom` command available and log a usage hint. |
|
| `install_headroom` | `true` | Register the baked-in `headroom` MCP server in Claude Desktop, exposing its `headroom_compress`/`headroom_retrieve`/`headroom_stats` context-compression tools inside the app. (Claude Desktop overrides `ANTHROPIC_BASE_URL`, so transparent proxy compression is not possible — MCP is the supported path; see [headroom #869](https://github.com/headroomlabs-ai/headroom/issues/869).) Disabling removes the entry again. |
|
||||||
| `install_rtk` | `true` | Configure the rtk Claude Code `PreToolUse` hook in the persistent Claude Code settings. |
|
| `install_rtk` | `true` | Configure the rtk Claude Code `PreToolUse` hook in the persistent Claude Code settings. |
|
||||||
| `install_caveman` | `true` | Install the caveman Claude Code plugin into the persistent Claude Code home. |
|
| `install_caveman` | `true` | Install the caveman Claude Code plugin into the persistent Claude Code home. |
|
||||||
| `install_github_cli` | `true` | Enable first-start checks and setup for the baked-in `git` and `gh` commands. |
|
| `install_github_cli` | `true` | Enable first-start checks and setup for the baked-in `git` and `gh` commands. |
|
||||||
|
|||||||
@@ -90,5 +90,5 @@ slug: claude_desktop
|
|||||||
tmpfs: true
|
tmpfs: true
|
||||||
udev: true
|
udev: true
|
||||||
url: https://github.com/alexbelgium/hassio-addons
|
url: https://github.com/alexbelgium/hassio-addons
|
||||||
version: "1.5"
|
version: "1.6"
|
||||||
video: true
|
video: true
|
||||||
|
|||||||
@@ -14,8 +14,18 @@ dbus-update-activation-environment --all >/dev/null 2>&1 || true
|
|||||||
# --password-store=gnome-libsecret forces Electron onto the libsecret backend instead of
|
# --password-store=gnome-libsecret forces Electron onto the libsecret backend instead of
|
||||||
# falling back to plaintext (and warning that the sign-in will not be saved).
|
# falling back to plaintext (and warning that the sign-in will not be saved).
|
||||||
CLAUDE_DESKTOP_COMMAND_FILE="/tmp/claude-desktop-command"
|
CLAUDE_DESKTOP_COMMAND_FILE="/tmp/claude-desktop-command"
|
||||||
|
DEFAULT_CLAUDE_DESKTOP_COMMAND="claude-desktop --no-sandbox --disable-dev-shm-usage --password-store=gnome-libsecret"
|
||||||
if [ -s "$CLAUDE_DESKTOP_COMMAND_FILE" ]; then
|
if [ -s "$CLAUDE_DESKTOP_COMMAND_FILE" ]; then
|
||||||
sh -c "$(cat "$CLAUDE_DESKTOP_COMMAND_FILE")"
|
CLAUDE_DESKTOP_COMMAND="$(cat "$CLAUDE_DESKTOP_COMMAND_FILE")"
|
||||||
else
|
else
|
||||||
claude-desktop --no-sandbox --disable-dev-shm-usage --password-store=gnome-libsecret
|
CLAUDE_DESKTOP_COMMAND="$DEFAULT_CLAUDE_DESKTOP_COMMAND"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Launch the configured command. If a custom/wrapped command fails to start, fall back to
|
||||||
|
# the plain Claude Desktop launch so the desktop app still comes up for the user.
|
||||||
|
if ! sh -c "$CLAUDE_DESKTOP_COMMAND"; then
|
||||||
|
if [ "$CLAUDE_DESKTOP_COMMAND" != "$DEFAULT_CLAUDE_DESKTOP_COMMAND" ]; then
|
||||||
|
echo "autostart: '$CLAUDE_DESKTOP_COMMAND' failed; falling back to default Claude Desktop launch" >&2
|
||||||
|
exec sh -c "$DEFAULT_CLAUDE_DESKTOP_COMMAND"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -8,13 +8,57 @@ CLAUDE_DESKTOP_COMMAND_FILE="/tmp/claude-desktop-command"
|
|||||||
DEFAULT_CLAUDE_DESKTOP_COMMAND='claude-desktop --no-sandbox --disable-dev-shm-usage --password-store=gnome-libsecret'
|
DEFAULT_CLAUDE_DESKTOP_COMMAND='claude-desktop --no-sandbox --disable-dev-shm-usage --password-store=gnome-libsecret'
|
||||||
printf '%s\n' "$DEFAULT_CLAUDE_DESKTOP_COMMAND" > "$CLAUDE_DESKTOP_COMMAND_FILE"
|
printf '%s\n' "$DEFAULT_CLAUDE_DESKTOP_COMMAND" > "$CLAUDE_DESKTOP_COMMAND_FILE"
|
||||||
|
|
||||||
|
# headroom's "wrap"/proxy routing works by setting ANTHROPIC_BASE_URL, which the Claude Desktop
|
||||||
|
# Electron app force-overrides to the production endpoint (headroom #869), so transparent
|
||||||
|
# compression cannot be applied to the desktop launch. The integration that does work with
|
||||||
|
# Claude Desktop is headroom's MCP server, which exposes the headroom_compress/headroom_retrieve/
|
||||||
|
# headroom_stats tools inside the app. Register it in Claude Desktop's MCP config, leaving the
|
||||||
|
# plain launch untouched. The merge is idempotent and preserves any other MCP servers.
|
||||||
|
CLAUDE_DESKTOP_CONFIG="$HOME/.config/Claude/claude_desktop_config.json"
|
||||||
if bashio::config.true 'install_headroom'; then
|
if bashio::config.true 'install_headroom'; then
|
||||||
if command -v headroom &> /dev/null; then
|
if command -v headroom &> /dev/null; then
|
||||||
bashio::log.info "headroom $(headroom --version 2> /dev/null || true) available; launching Claude Desktop through headroom"
|
bashio::log.info "headroom $(headroom --version 2> /dev/null || true) available; registering the headroom MCP server for Claude Desktop"
|
||||||
printf '%s\n' "headroom wrap $DEFAULT_CLAUDE_DESKTOP_COMMAND" > "$CLAUDE_DESKTOP_COMMAND_FILE"
|
HEADROOM_BIN="$(command -v headroom)" CLAUDE_DESKTOP_CONFIG="$CLAUDE_DESKTOP_CONFIG" python3 - <<'PY' || bashio::log.warning "Unable to register the headroom MCP server automatically"
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
path = Path(os.environ["CLAUDE_DESKTOP_CONFIG"])
|
||||||
|
try:
|
||||||
|
data = json.loads(path.read_text()) if path.exists() else {}
|
||||||
|
if not isinstance(data, dict):
|
||||||
|
data = {}
|
||||||
|
except Exception:
|
||||||
|
if path.exists():
|
||||||
|
path.rename(path.with_suffix(path.suffix + ".bak"))
|
||||||
|
data = {}
|
||||||
|
servers = data.get("mcpServers")
|
||||||
|
if not isinstance(servers, dict):
|
||||||
|
servers = {}
|
||||||
|
data["mcpServers"] = servers
|
||||||
|
servers["headroom"] = {"command": os.environ.get("HEADROOM_BIN", "headroom"), "args": ["mcp", "serve"]}
|
||||||
|
path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
path.write_text(json.dumps(data, indent=2) + "\n")
|
||||||
|
PY
|
||||||
else
|
else
|
||||||
bashio::log.warning "headroom is not available"
|
bashio::log.warning "headroom is not available"
|
||||||
fi
|
fi
|
||||||
|
elif [ -f "$CLAUDE_DESKTOP_CONFIG" ]; then
|
||||||
|
bashio::log.info "Removing the headroom MCP server from Claude Desktop"
|
||||||
|
CLAUDE_DESKTOP_CONFIG="$CLAUDE_DESKTOP_CONFIG" python3 - <<'PY' || bashio::log.warning "Unable to remove the headroom MCP server automatically"
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
path = Path(os.environ["CLAUDE_DESKTOP_CONFIG"])
|
||||||
|
data = json.loads(path.read_text())
|
||||||
|
if isinstance(data, dict):
|
||||||
|
servers = data.get("mcpServers")
|
||||||
|
if isinstance(servers, dict) and servers.pop("headroom", None) is not None:
|
||||||
|
if not servers:
|
||||||
|
data.pop("mcpServers", None)
|
||||||
|
path.write_text(json.dumps(data, indent=2) + "\n")
|
||||||
|
PY
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if bashio::config.true 'install_rtk'; then
|
if bashio::config.true 'install_rtk'; then
|
||||||
|
|||||||
Reference in New Issue
Block a user