Files
hassio-addons/claude_desktop
alexbelgium 26101a1104 fix(claude_desktop): guard env parsing and truncate file-list arrays in headroom hook
Two review findings on PR #2871:

- coderabbitai: MIN_CHARS/MIN_SAVED_TOKENS parsed with a bare int() at module
  import time, before any try/except could catch a bad value — a malformed
  env_vars passthrough would crash the hook on every matched tool call instead
  of failing open as documented. Wrapped in _int_env() with a safe fallback.

- chatgpt-codex-connector: Glob and Grep (files_with_matches mode) return a
  `filenames: string[]` field per the CLI's own output schema, which the
  hook's string-only candidate scan never touched — large file listings, the
  exact case named in the CLAUDE.md guidance this add-on installs, passed
  through uncompressed. Verified empirically that routing such an array
  through compress()/SmartCrusher (as done for JSON-blob string fields)
  silently subsamples it — 600 paths collapsed to ~15 with no visible marker,
  unsafe for paths the model needs to act on individually. Added a separate
  deterministic path: arrays over ARRAY_KEEP (40) entries are truncated in
  order with one labeled marker entry appended, full array recoverable from
  the CCR store by hash. Verified round-trip on Glob- and Grep-shaped
  payloads (600 and 200 entries); confirmed order preservation and that
  small arrays still pass through untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 14:46:10 +02:00
..
2026-07-16 08:40:49 +02:00
2026-07-12 23:21:20 +00:00
2026-07-12 23:21:20 +00:00
2026-07-12 23:21:20 +00:00

Home assistant add-on: Claude Desktop

Supports aarch64 Architecture Supports amd64 Architecture Project Maintenance

Run Claude Desktop in a LinuxServer.io Selkies add-on, with Headroom context compression, RTK Bash-output acceleration, and TokenSave semantic code intelligence wired in by default.

Installation

  1. Add this repository to the Home Assistant add-on store.
  2. Install Claude Desktop.
  3. Start the add-on and open the web UI from the sidebar.
  4. Sign in with your Claude account from the Desktop app.

Claude Desktop sign-in requires a claude.ai plan that supports the Desktop app. API keys are not accepted by the Desktop application. Anthropic's Linux beta currently does not include Computer Use or dictation.

Architecture

Everything is built around the Claude Desktop app. Claude Code is installed in the same image but is not exposed as a standalone service: Claude Desktop's cowork and dispatch sessions run it internally, and they pick up the shared Claude Code configuration (~/.claude), hooks, MCP servers, permissions, and PATH tools.

  • Claude Desktop uses Headroom through its MCP tools.
  • Claude Code sessions inside Desktop get the same MCP servers, permission mode, and RTK/TokenSave hooks through the shared Claude Code configuration.
  • PATH-based Claude Code launches are routed through the supervised Headroom proxy when headroom_wrap_claude_code is enabled. If a Desktop release calls /usr/bin/claude directly, the session remains functional and still has the shared permission mode and Headroom MCP tools, but transparent proxy compression cannot be injected.
  • The shared abc desktop account runs under the configured PUID/PGID (default 1000:1000). When permission_mode: bypass is selected while PUID is 0, the add-on automatically falls back to UID 1000 before Selkies and Claude Desktop start, because Claude Code refuses bypass mode under an effective root UID.
  • gnome-keyring provides the Secret Service backend Electron needs to persist sign-in and dispatch permission grants across restarts.

Optimization layers

The three bundled optimization tools are complementary:

  • RTK rewrites supported Bash commands so Claude receives compact output.
  • TokenSave builds a local semantic graph for explicitly selected code repositories and steers Claude away from repeated Explore/Grep/Read fan-out.
  • Headroom transparently compresses proxied Claude Code traffic and also exposes on-demand compress/retrieve/statistics MCP tools to Claude Desktop.

TokenSave's complete Claude integration is installed at startup: MCP server, permissions, PreToolUse/UserPromptSubmit/Stop hooks, global prompt rules, and Git synchronization hooks. A repository is indexed only when it is listed in tokensave_project_paths; no automatic filesystem scan is performed.

Features

  • Claude Desktop in single-app Selkies mode with Home Assistant ingress.
  • Official Claude Code stable package powering Desktop cowork/dispatch sessions.
  • Persistent $HOME at the configured data_location (default /data/data), preserving Desktop and Claude Code state across restarts.
  • Persistent sign-in through a bundled, auto-unlocked gnome-keyring.
  • Configurable Claude Code permissions: strict prompts, automatic safe-action approval, or explicit full bypass for trusted installations.
  • Automatic non-root runtime enforcement for bypass mode, including root-console wrapper launches.
  • Optional runtime Claude Desktop updates from Anthropic's apt repository.
  • Optional extra apt and pip package installation (pip installs use uv).
  • Baked-in git, GitHub CLI (gh), ripgrep, jq, shellcheck, yamllint, hadolint, and actionlint.
  • Custom script support through the repository standard claude_desktop.sh.
  • Bundled optimization tools: Headroom, RTK, and TokenSave; Caveman remains available as an opt-in plugin.
  • Optional Home Assistant MCP bridge so Claude can query and control Home Assistant.
  • Independent hourly savings reports for Headroom, RTK, and TokenSave.
  • claude-tools-doctor.sh diagnostics for binaries, routing, hooks, MCP registrations, project indexes, proxy health, permissions, runtime identity, and gains.
  • Low-power defaults for GPU mapping, Selkies frame rate, and volatile caches.

Options

Option Default Description
PUID / PGID 1000 / 1000 Numeric user and group of the shared abc desktop account that owns the data location and runs Claude Desktop. In bypass mode, a root PUID is automatically replaced at runtime by UID 1000 while the configured group is retained.
TZ Optional timezone, for example Europe/Brussels.
KEYBOARD Optional Selkies keyboard layout.
PASSWORD Optional password for direct Selkies ports.
DRINODE Optional GPU device override for Selkies.
DNS_server 8.8.8.8 DNS server used by the standard DNS module.
auto_update true Upgrade claude-desktop from Anthropic's apt repository at startup.
permission_mode auto Claude Code permission policy: strict, auto, or bypass.
install_headroom true Register Headroom MCP and run the supervised local proxy.
headroom_wrap_claude_code true Route PATH-based Claude Code launches through the already-running Headroom proxy.
headroom_auto_compress true Auto-compress large tool outputs in every Claude Code session via a managed PostToolUse hook.
expose_headroom_dashboard false Bind Headroom to all interfaces. Port 8787/tcp must also be mapped manually.
install_rtk true Configure RTK's Claude Code PreToolUse Bash hook.
install_tokensave true Install TokenSave's complete global Claude integration.
tokensave_project_paths [] Explicit absolute Git repository paths to initialize or sync at startup.
install_caveman false Install the third-party Caveman Claude Code plugin at startup.
enable_tools_health_report true Write independent Headroom, RTK, and TokenSave gains to the add-on log hourly.
install_github_cli true Enable setup checks for the baked-in git and gh commands.
github_token Optional GitHub token used to authenticate gh and Git operations.
github_username Optional global Git author name.
github_email Optional global Git author email.
enable_ha_mcp false Register Home Assistant's MCP server in Claude (requires ha_mcp_token).
ha_mcp_url http://homeassistant:8123/api/mcp Streamable HTTP endpoint of Home Assistant's MCP Server integration.
ha_mcp_token Home Assistant long-lived access token used by the MCP bridge.
enable_ha_api_helper true Ship the ha-cli Core-API helper and add guidance so Claude can configure Home Assistant without a /config mount.
additional_apps Comma-separated Debian apt packages to install at startup.
additional_pip Comma-separated pip packages installed at startup (via uv).
data_location /data/data Persistent home directory for Claude and tooling.
env_vars [] Additional environment variables exported inside the container.

Permission modes

permission_mode: auto
  • strict keeps Claude Code's normal interactive permission prompts.
  • auto asks Claude Code's automatic permission classifier to approve safe operations while retaining prompts for risky actions. This is the default.
  • bypass disables Claude Code permission checks by using bypassPermissions in the shared settings and --dangerously-skip-permissions for wrapper-launched sessions.

Claude Code does not permit bypass mode when its effective UID is 0. If the add-on is configured with PUID: 0, selecting bypass runs the shared abc runtime account as UID 1000 instead, before storage ownership and Desktop startup. Its configured primary GID is retained, so group-based access to mounted Home Assistant paths remains available. Strict and auto modes keep the configured identity unchanged.

A root shell invoking /usr/local/bin/claude in bypass mode is also dropped to the remapped abc account. Directly invoking /usr/bin/claude as root still bypasses the add-on wrapper and will be rejected by Claude Code.

bypass gives Claude broad authority over all mounted writable data and every command or credential available inside the add-on. Enable it only in a trusted installation with trusted repositories and mounts. Mounted paths must remain accessible to the effective non-root UID or its retained group.

TokenSave project example

Only repositories listed here are indexed. Paths must be absolute, mounted in the add-on, and resolve to a Git working tree:

tokensave_project_paths:
  - /share/projects/hassio-addons
  - /share/projects/birdnet-go

At startup, an uninitialized repository receives tokensave init; an existing index receives an incremental tokensave sync. Removing a path from the option stops automatic synchronization but does not delete its .tokensave database. Configured repositories are added to Git's safe.directory list for the shared runtime user before TokenSave performs repository discovery.

Headroom behavior

When install_headroom is enabled, the add-on registers headroom mcp serve with the explicit local proxy URL in Claude Desktop and Claude Code, then starts a supervised Headroom backend on 127.0.0.1:8787.

Claude Desktop overrides ANTHROPIC_BASE_URL, so Desktop chat deliberately uses the MCP integration. The /usr/local/bin/claude wrapper routes PATH-based Claude Code sessions through headroom wrap claude --no-proxy, reusing the supervised backend without starting a second proxy.

With headroom_auto_compress enabled (the default), a managed Claude Code PostToolUse hook additionally compresses large Bash/Grep/Glob/WebFetch outputs (over ~4000 characters) in every session type — terminal, Desktop cowork, dispatch, and cron — without the model having to remember to call the MCP tools. The original output is kept in Headroom's local store for one hour and can always be recovered with mcp__headroom__headroom_retrieve using the hash printed in the compression marker. Error text (stderr) is never compressed, and plain prose passes through unchanged; the savings come from structured output such as JSON dumps, search results, and logs.

The dashboard is disabled externally by default. To expose it:

  1. Set expose_headroom_dashboard: true.
  2. Map 8787/tcp in the add-on Network section.
  3. Open http://<home-assistant-host>:8787/dashboard.

The dashboard is unauthenticated. Do not publish this port to the public internet.

Diagnostics

Run the following inside the add-on through a custom script or container console:

claude-tools-doctor.sh

The report checks the tool binaries, configuration switches, configured and effective runtime identities, redacted MCP registrations, Claude hooks, permission mode, Headroom health, TokenSave indexes, routing, and recorded savings. It never prints MCP environment values because the Home Assistant MCP entry can contain a long-lived token.

The hourly report can also be invoked manually:

claude-gains-report.sh

Home Assistant MCP bridge

To let Claude query and control Home Assistant:

  1. In Home Assistant, add the Model Context Protocol Server integration (Settings → Devices & services → Add integration).
  2. Create a long-lived access token (your profile → Security).
  3. Set enable_ha_mcp: true and paste the token into ha_mcp_token in the add-on configuration, then restart the add-on.

The add-on bridges Claude to the integration's stateless Streamable HTTP endpoint (/api/mcp) with mcp-proxy. Override ha_mcp_url only if your Home Assistant instance is not reachable as homeassistant:8123 from add-ons.

Configuring Home Assistant (API helper)

When enable_ha_api_helper is on (the default), the add-on ships a ha-cli command and tells Claude — via a managed block in ~/.claude/CLAUDE.md — that it can configure Home Assistant through the Home Assistant Core API rather than a filesystem mount. This is deliberately more contained than mapping /config: the API cannot read configuration.yaml, secrets.yaml, or any other add-on's stored credentials.

ha-cli authenticates automatically with the add-on's SUPERVISOR_TOKEN through the Supervisor Core-API proxy (the add-on already sets homeassistant_api: true), so there is nothing to configure. It can create and edit automations, scripts, and scenes; call any service; read entity states; and, over WebSocket, manage helpers, dashboards, and the area/label/floor/entity registries. Run ha-cli --help inside the add-on for the full command reference.

ha-cli config                                   # connectivity check
ha-cli get config/automation/config/<id>        # read one automation
ha-cli post config/automation/config/<id> @new.json   # create/update it
ha-cli call automation.reload                   # apply YAML-mode changes
ha-cli ws '{"type":"config/area_registry/list"}'

Security notes:

  • The Supervisor proxy token grants admin-equivalent Core API access (it can call any service and edit any UI-managed configuration), but it cannot reach the raw YAML files or other add-ons' data. For a tighter scope, set HA_BASE_URL/HA_TOKEN (or the ha_mcp_token option) to a limited Home Assistant user's long-lived token — ha-cli prefers those when present.
  • The guidance instructs Claude to read each object and show you the intended change before writing, but Claude Code's own tool-permission prompts remain the real gate: each ha-cli call still needs your approval unless permission_mode is set to bypass.
  • Set enable_ha_api_helper: false to remove both the guidance block and the helper's registration if you do not want Claude configuring Home Assistant.

Custom scripts

The add-on includes the repository standard custom-script executor. On first start, it seeds claude_desktop.sh in the add-on config directory. Commands in that script run during startup, allowing local customization without rebuilding the image.

Data and cache locations

Persistent state is stored in the configured data_location (default /data/data):

  • Claude Desktop sign-in: ~/.config/Claude (token encrypted via gnome-keyring; keyring DB in ~/.local/share/keyrings)
  • Claude Code settings, hooks, sessions, plugins, and permission mode: ~/.claude
  • Headroom, RTK, and TokenSave user state: their standard paths below the shared home
  • TokenSave repository indexes: .tokensave/ inside each explicitly configured project

Volatile cache data is redirected to /tmp/cache through $XDG_CACHE_HOME and $HOME/.cache.