Claude Code for Home Assistant: slim fork v1.2.65 (Proxmox "Killed" fix, working auto-update, smoother OAuth)

First and most important: full credit to @robsonfelix. His original app, Claude Code for Home Assistant - AI Assistant directly in your HA!, is the foundation this fork is built on. Almost every line of the Dockerfile started in his repo. This post is not a replacement for his thread, just a place where folks who hit specific install/runtime issues can land.

A handful of recurring problems were reported in the original thread:

  • The app getting Killed repeatedly on startup on Proxmox HAOS and other small-VM setups.
  • Auto-update never actually pulling new Claude Code releases, leaving users stuck on old versions.
  • The OAuth auth-code paste flow being painful: tmux intercepting paste, URLs wrapping across lines, repeated 400 errors.
  • A first-launch jq: error: ... settings.json: No such file or directory that silently broke the pre-authorized tools list.
  • Two Supervisor warnings on install (selective device access and deprecated arch values).

Rather than send drive-by patches and leave folks stuck in the meantime, I forked the repo, stripped it down to just the Claude Code app, and shipped fixes targeted at those exact issues.

What’s different in v1.2.65

  • “Killed on startup” on Proxmox and small VMs. auto_update_claude now defaults to false. When you do enable it, npm install -g @anthropic-ai/claude-code@latest runs in the background with a 90s timeout, so it never blocks ttyd from coming up. NODE_OPTIONS=--max-old-space-size=512 caps Node’s heap to keep the OOM killer off our back. tmux scrollback dropped from 20,000 to 5,000 lines. Healthcheck start-period raised from 10s to 120s so Supervisor stops killing the app mid-boot.
  • Auto-update actually picks up new releases. Replaced npm update -g (a near-no-op for global packages on npm 9+) with npm install -g @anthropic-ai/claude-code@latest.
  • OAuth paste flow. session_persistence now defaults to false so tmux isn’t intercepting paste during first-time auth. tmux still sets set-clipboard on and allow-passthrough on for users who keep persistence enabled. Expanded README troubleshooting for the “long URL wraps and you copy half of it” case.
  • First-launch jq error fixed. Startup now creates settings.json if missing before merging the pre-authorized tools list. Without this fix, every read tool prompted for permission in the first claude session, defeating the whole pre-auth.
  • Supervisor warnings cleaned up. Removed redundant uart: true (subsumed by full_access: true) and trimmed arch: to the still-supported amd64 and aarch64 only.
  • Slimmer repo. Only the Claude Code app. The original Alexa Monocle bridge and the standalone Playwright Browser app are not in this fork; if you want them, they remain in the upstream repo.

Install

Click to add the repository:

Add Repository

Or manually: Settings → Apps → App Store → ⋮ → Repositories, add https://github.com/sproft/hass-claude.

Then install Claude Code from the store and start it. First launch will walk you through Anthropic auth from the terminal.

If you’ve been stuck

If you’ve been hitting any of the issues above on the original app, give v1.2.65 a try. Drop a reply with logs (Settings → Apps → Claude Code → Log) if something still doesn’t work. I’d rather hear about it than have you give up.

PRs welcome. Issues welcome. The repo is at GitHub - sproft/hass-claude: Home Assisstant Claude Code - run Anthropic's AI coding assistant directly in Home Assistant to create automations and manage your smart home. · GitHub.

Thanks again @robsonfelix. Your app is genuinely one of the most useful things I’ve installed in HA, and this fork only exists because the foundation was already there. :folded_hands:

Add-ons as a term has been removed some months ago now. I suggest updating your text here to use the word Apps.

thanks for the tip, I have have always used the terms interchangeably, but of course going forward app should be used.

1 Like

I gave it a try, and it worked without any problems :slight_smile: :slight_smile:

Sadly I am having no luck with this.

I also can’t open an issue on GitHub

[2026/05/06 16:01:38:7458] N: __lws_lc_tag:  ++ [wsisrv|0|adopted] (1)
[2026/05/06 16:01:38:7459] N: HTTP / - 127.0.0.1
[2026/05/06 16:01:38:7549] N: __lws_lc_untag:  -- [wsisrv|0|adopted] (0) 9.157ms
[2026/05/06 16:02:08:8356] N: __lws_lc_tag:  ++ [wsisrv|1|adopted] (1)
[2026/05/06 16:02:08:8358] N: HTTP / - 127.0.0.1
[2026/05/06 16:02:08:8412] N: __lws_lc_untag:  -- [wsisrv|1|adopted] (0) 5.604ms
[2026/05/06 16:02:38:8809] N: __lws_lc_tag:  ++ [wsisrv|2|adopted] (1)
[2026/05/06 16:02:38:8810] N: HTTP / - 127.0.0.1
[2026/05/06 16:02:38:8849] N: __lws_lc_untag:  -- [wsisrv|2|adopted] (0) 3.966ms
[2026/05/06 16:03:08:9314] N: __lws_lc_tag:  ++ [wsisrv|3|adopted] (1)
[2026/05/06 16:03:08:9315] N: HTTP / - 127.0.0.1
[2026/05/06 16:03:08:9356] N: __lws_lc_untag:  -- [wsisrv|3|adopted] (0) 4.113ms
[2026/05/06 16:03:38:9814] N: __lws_lc_tag:  ++ [wsisrv|4|adopted] (1)
[2026/05/06 16:03:38:9815] N: HTTP / - 127.0.0.1
[2026/05/06 16:03:38:9852] N: __lws_lc_untag:  -- [wsisrv|4|adopted] (0) 3.786ms
[2026/05/06 16:04:09:0264] N: __lws_lc_tag:  ++ [wsisrv|5|adopted] (1)
[2026/05/06 16:04:09:0265] N: HTTP / - 127.0.0.1
[2026/05/06 16:04:09:0318] N: __lws_lc_untag:  -- [wsisrv|5|adopted] (0) 5.400ms
[2026/05/06 16:04:12:8268] N: __lws_lc_tag:  ++ [wsisrv|6|adopted] (1)
[2026/05/06 16:04:12:8276] N: HTTP / - 172.30.32.2
[2026/05/06 16:04:12:9330] N: HTTP /token - 172.30.32.2
[2026/05/06 16:04:12:9981] N: WS   /ws - 172.30.32.2, clients: 1
[2026/05/06 16:04:12:9990] N: started process, pid: 136
[2026/05/06 16:04:39:2364] N: __lws_lc_tag:  ++ [wsisrv|7|adopted] (2)
[2026/05/06 16:04:39:2366] N: HTTP / - 127.0.0.1
[2026/05/06 16:04:39:2452] N: __lws_lc_untag:  -- [wsisrv|7|adopted] (1) 8.823ms
[2026/05/06 16:05:09:2855] N: __lws_lc_tag:  ++ [wsisrv|8|adopted] (2)
[2026/05/06 16:05:09:2857] N: HTTP / - 127.0.0.1
[2026/05/06 16:05:09:2910] N: __lws_lc_untag:  -- [wsisrv|8|adopted] (1) 5.443ms
[2026/05/06 16:05:39:3355] N: __lws_lc_tag:  ++ [wsisrv|9|adopted] (2)
[2026/05/06 16:05:39:3357] N: HTTP / - 127.0.0.1
[2026/05/06 16:05:39:3397] N: __lws_lc_untag:  -- [wsisrv|9|adopted] (1) 4.160ms
[2026/05/06 16:06:09:4010] N: __lws_lc_tag:  ++ [wsisrv|a|adopted] (2)
[2026/05/06 16:06:09:4012] N: HTTP / - 127.0.0.1
[2026/05/06 16:06:09:4046] N: __lws_lc_untag:  -- [wsisrv|a|adopted] (1) 3.593ms
[2026/05/06 16:06:36:6937] N: WS closed from 172.30.32.2, clients: 0
[2026/05/06 16:06:36:6937] N: killing process, pid: 136
[2026/05/06 16:06:36:6938] N: __lws_lc_untag:  -- [wsisrv|6|adopted] (0) 2.397min
[2026/05/06 16:06:36:6952] N: process killed with signal 1, pid: 136
[2026/05/06 16:06:39:4535] N: __lws_lc_tag:  ++ [wsisrv|b|adopted] (1)
[2026/05/06 16:06:39:4539] N: HTTP / - 127.0.0.1
[2026/05/06 16:06:39:4568] N: __lws_lc_untag:  -- [wsisrv|b|adopted] (0) 3.315ms
[2026/05/06 16:07:09:5036] N: __lws_lc_tag:  ++ [wsisrv|c|adopted] (1)
[2026/05/06 16:07:09:5037] N: HTTP / - 127.0.0.1
[2026/05/06 16:07:09:5093] N: __lws_lc_untag:  -- [wsisrv|c|adopted] (0) 5.769ms
[2026/05/06 16:07:39:5591] N: __lws_lc_tag:  ++ [wsisrv|d|adopted] (1)
[2026/05/06 16:07:39:5592] N: HTTP / - 127.0.0.1
[2026/05/06 16:07:39:5637] N: __lws_lc_untag:  -- [wsisrv|d|adopted] (0) 4.621ms
[2026/05/06 16:08:09:6066] N: __lws_lc_tag:  ++ [wsisrv|e|adopted] (1)
[2026/05/06 16:08:09:6071] N: HTTP / - 127.0.0.1
[2026/05/06 16:08:09:6146] N: __lws_lc_untag:  -- [wsisrv|e|adopted] (0) 7.988ms
[2026/05/06 16:08:39:7093] N: __lws_lc_tag:  ++ [wsisrv|f|adopted] (1)
[2026/05/06 16:08:39:7108] N: HTTP / - 127.0.0.1
[2026/05/06 16:08:39:7169] N: __lws_lc_untag:  -- [wsisrv|f|adopted] (0) 7.524ms
[2026/05/06 16:09:09:7524] N: __lws_lc_tag:  ++ [wsisrv|10|adopted] (1)
[2026/05/06 16:09:09:7525] N: HTTP / - 127.0.0.1
[2026/05/06 16:09:09:7559] N: __lws_lc_untag:  -- [wsisrv|10|adopted] (0) 3.554ms
[2026/05/06 16:09:39:7930] N: __lws_lc_tag:  ++ [wsisrv|11|adopted] (1)
[2026/05/06 16:09:39:7931] N: HTTP / - 127.0.0.1
[2026/05/06 16:09:39:7971] N: __lws_lc_untag:  -- [wsisrv|11|adopted] (0) 4.124ms
[2026/05/06 16:09:49:0413] N: __lws_lc_tag:  ++ [wsisrv|12|adopted] (1)
[2026/05/06 16:09:49:0415] N: HTTP / - 172.30.32.2
[2026/05/06 16:09:49:1390] N: HTTP /token - 172.30.32.2
[2026/05/06 16:09:49:1786] N: WS   /ws - 172.30.32.2, clients: 1
[2026/05/06 16:09:49:1830] N: started process, pid: 219
[2026/05/06 16:10:09:9323] N: __lws_lc_tag:  ++ [wsisrv|13|adopted] (2)
[2026/05/06 16:10:09:9327] N: HTTP / - 127.0.0.1
[2026/05/06 16:10:09:9382] N: __lws_lc_untag:  -- [wsisrv|13|adopted] (1) 5.943ms
[2026/05/06 16:10:39:9763] N: __lws_lc_tag:  ++ [wsisrv|14|adopted] (2)
[2026/05/06 16:10:39:9764] N: HTTP / - 127.0.0.1
[2026/05/06 16:10:39:9809] N: __lws_lc_untag:  -- [wsisrv|14|adopted] (1) 4.663ms
[2026/05/06 16:11:00:1675] N: WS closed from 172.30.32.2, clients: 0
[2026/05/06 16:11:00:1676] N: killing process, pid: 219
[2026/05/06 16:11:00:1678] N: __lws_lc_untag:  -- [wsisrv|12|adopted] (0) 1.185min
[2026/05/06 16:11:00:1737] N: process killed with signal 1, pid: 219
[2026/05/06 16:11:10:0416] N: __lws_lc_tag:  ++ [wsisrv|15|adopted] (1)
[2026/05/06 16:11:10:0425] N: HTTP / - 127.0.0.1
[2026/05/06 16:11:10:0509] N: __lws_lc_untag:  -- [wsisrv|15|adopted] (0) 9.258ms
[2026/05/06 16:11:40:0969] N: __lws_lc_tag:  ++ [wsisrv|16|adopted] (1)
[2026/05/06 16:11:40:0972] N: HTTP / - 127.0.0.1
[2026/05/06 16:11:40:1081] N: __lws_lc_untag:  -- [wsisrv|16|adopted] (0) 11.206ms
[2026/05/06 16:12:10:1508] N: __lws_lc_tag:  ++ [wsisrv|17|adopted] (1)
[2026/05/06 16:12:10:1509] N: HTTP / - 127.0.0.1
[2026/05/06 16:12:10:1571] N: __lws_lc_untag:  -- [wsisrv|17|adopted] (0) 6.304ms
[2026/05/06 16:12:40:2194] N: __lws_lc_tag:  ++ [wsisrv|18|adopted] (1)
[2026/05/06 16:12:40:2195] N: HTTP / - 127.0.0.1
[2026/05/06 16:12:40:2259] N: __lws_lc_untag:  -- [wsisrv|18|adopted] (0) 6.486ms
[2026/05/06 16:13:10:2684] N: __lws_lc_tag:  ++ [wsisrv|19|adopted] (1)
[2026/05/06 16:13:10:2686] N: HTTP / - 127.0.0.1
[2026/05/06 16:13:10:2720] N: __lws_lc_untag:  -- [wsisrv|19|adopted] (0) 3.656ms
[2026/05/06 16:13:40:3379] N: __lws_lc_tag:  ++ [wsisrv|1a|adopted] (1)
[2026/05/06 16:13:40:3380] N: HTTP / - 127.0.0.1
[2026/05/06 16:13:40:3427] N: __lws_lc_untag:  -- [wsisrv|1a|adopted] (0) 4.827ms
[2026/05/06 16:14:10:3809] N: __lws_lc_tag:  ++ [wsisrv|1b|adopted] (1)
[2026/05/06 16:14:10:3810] N: HTTP / - 127.0.0.1
[2026/05/06 16:14:10:3864] N: __lws_lc_untag:  -- [wsisrv|1b|adopted] (0) 5.430ms
[2026/05/06 16:14:24:0310] N: received signal: SIGTERM (15), exiting...
[2026/05/06 16:14:24:0310] N: send ^C to force exit.
/bin/bash: line 2:    22 Killed                  claude mcp remove homeassistant -s user 2> /dev/null
/bin/bash: line 2:    53 Killed                  claude mcp remove playwright -s user 2> /dev/null
/bin/bash: line 2:    76 Killed                  claude mcp add-json homeassistant '{"command":"hass-mcp"}' -s user
/bin/bash: line 2: : No such file or directory
jq: error: Could not open file : No such file or directory
[WARN] Failed to write pre-authorized tools to settings.json - read tools will require manual approval on first use
[INFO] Updating Claude Code in background (timeout 90s)...
[2026/05/06 16:17:30:7187] N: ttyd 1.7.7-40e79c7 (libwebsockets 4.3.3-unknown)
[2026/05/06 16:17:30:7228] N: tty configuration:
[2026/05/06 16:17:30:7229] N:   start command: bash --login
[2026/05/06 16:17:30:7229] N:   close signal: SIGHUP (1)
[2026/05/06 16:17:30:7229] N:   terminal type: xterm-256color
[2026/05/06 16:17:30:7229] N:   max clients: 5
[2026/05/06 16:17:30:7475] N: lws_create_context: LWS: 4.3.3-unknown, MbedTLS-2.28.5 NET SRV H1 H2 WS ConMon IPV6-off
[2026/05/06 16:17:30:7480] N: elops_init_pt_uv:  Using foreign event loop...
[2026/05/06 16:17:30:7480] N: __lws_lc_tag:  ++ [wsi|0|pipe] (1)
[2026/05/06 16:17:30:7481] N: __lws_lc_tag:  ++ [vh|0|netlink] (1)
[2026/05/06 16:17:30:7482] N: __lws_lc_tag:  ++ [vh|1|default||7681] (2)
[2026/05/06 16:17:30:7482] N: [vh|1|default||7681]: lws_socket_bind: source ads 0.0.0.0
[2026/05/06 16:17:30:7482] N: __lws_lc_tag:  ++ [wsi|1|listen|default||7681] (2)
[2026/05/06 16:17:30:7482] N:  Listening on port: 7681
[2026/05/06 16:17:30:9256] N: __lws_lc_tag:  ++ [wsisrv|0|adopted] (1)
[2026/05/06 16:17:30:9309] N: HTTP / - 127.0.0.1
[2026/05/06 16:17:30:9800] N: __lws_lc_untag:  -- [wsisrv|0|adopted] (0) 54.379ms
[WARN] Claude Code update failed/timed out (see /tmp/claude-update.log)

heyo, apparently github turns off issues by default when you fork a repository. Don't know why they do that, but know you can open issues there.

I have taken the liberty the open an Issue for your problem and will try to fix it.

Thanks for the detailed log, that was a real bug. Fixed in v1.2.66, just pushed.

What was happening: at boot, the addon ran three claude mcp ... commands back-to-back (remove old entries, then add the homeassistant one). Each one spawns a Node process at around 150 MB resident, and on a memory-tight Proxmox VM the kernel OOM killer was taking all three. Once claude mcp add-json died, the script's && chain broke and SETTINGS_FILE=... never got assigned, which is why the next line in your log had jq: error: Could not open file : with the empty filename. ttyd would still come up so the addon looked alive, but MCP wasn't actually wired up and the read-tool allowlist never landed, so every claude session would have prompted for every read.

v1.2.66 swaps those three CLI calls for direct jq edits to ~/.claude.json. Same end state, but jq does the JSON edit at around 5 MB instead of 150 MB, so OOM stops being a concern at boot. The variable assignments and the {} bootstrap of both JSON files now happen unconditionally, so even if anything else fails the rest of the script still has valid filenames to work with.

To pull it: Settings → Apps → App Store → ⋮ → Reload, then the Claude Code app page should show Update (1.2.65 → 1.2.66). Click it and restart. Your boot log should look like:

[INFO] MCP configured with Home Assistant integration
[INFO] Pre-authorized read-only MCP tools
[INFO] auto_update_claude disabled - skipping update

with no Killed or jq: error lines.

If you still see anything off, paste a fresh log and I'll have another look.

Nearly there. It still says killed when I run Claude for the first time. The VM is 4GB.

Just as a datapoint, I'm running mine in an Ubuntu QEMU/KVM VM (HAOS) with 4GB memory, but the VM is not running a lot of other stuff.

In my case it is both a memory issue but also...

Features: jsc no_avx2 no_avx standalone_executable claude_code

The CPU does NOT support AVX :frowning:

You may not know, but just glancing at the Dockerfile, I'm wondering why this (and the original repository) has pymodbus. That's a protocol for talking to Modbus IOT devices which shouldn't apply here??

Thanks for the reports, all three of these are useful.

@Arrival2738, the 1.2.66 fix was specifically for the boot-time claude mcp
calls. The kill you are now seeing happens later, when you run claude
interactively for the first time, which is a different code path. From the
addon log alone "Killed" looks the same in both cases, but two distinct
things can produce it:

  1. Real OOM. Bun (the runtime claude 2.x is bundled with) has a heavier
    startup working set than plain Node. With HA Core, Supervisor, the addon
    container, and ttyd all resident on a 4 GB VM, the first OAuth + first
    prompt can push past the cgroup ceiling. The addon's
    NODE_OPTIONS=--max-old-space-size=512 does not apply to Bun, so it is
    not constraining claude here.

  2. SIGILL (illegal instruction) from a CPU feature mismatch. The
    standalone Bun bundle Claude Code 2.x ships used to require AVX2, then
    later AVX. On a CPU that lacks the feature, the kernel kills the
    process and the addon log just shows "Killed". The
    Features: jsc no_avx2 no_avx ... line you posted is Bun's own
    runtime self-report on what it has compiled out, but you are stuck on
    2.1.109, and the no-AVX baseline bundle landed in newer 2.1.x releases.

Two diagnostic commands from the addon Terminal will tell us which one
it is:

dmesg | tail -30

"Out of memory: Killed process ... (claude.exe)" is case 1, real OOM.
"traps: claude.exe[...] trap invalid opcode" is case 2, SIGILL.

claude --version

confirms what the addon is actually running today. Latest on npm is
2.1.133, so 2.1.109 is two dozen patch releases behind.

If dmesg says "invalid opcode", the fix is to update past 2.1.109. The
reason your auto-update has been silently failing is the hard-coded 90 s
timeout on npm install -g @anthropic-ai/claude-code@latest, which is
too tight for a memory- and bandwidth-tight Proxmox VM. PR #7 raises the
default to 300 s and exposes it as claude_update_timeout. Once 1.2.67
ships you can also do npm install -g @anthropic-ai/claude-code@latest
from the addon Terminal manually as a one-shot.

If dmesg says OOM, more VM RAM (or shedding other workload during first
launch) is the practical fix. Removing NODE_OPTIONS would not help, since
Bun ignores it.

Filed as claude is Killed at first interactive launch (separate from boot-OOM fixed in #5) · Issue #8 · sproft/hass-claude · GitHub so we have a
place to follow up with the dmesg output.

@wmaker, you are right about pymodbus / pyserial. Inherited from upstream
with a comment "for Modbus operations", but nothing in this addon
container actually uses them. Modbus in HA lives in HA Core's integration.
Just dropped them on PR #7.

PR #7 (Make auto-update timeout configurable, append update log, add CI by sproft-bot · Pull Request #7 · sproft/hass-claude · GitHub) currently bundles
for 1.2.67:

  • claude_update_timeout option (default 300 s, range 30..1800)
    replacing the hard-coded 90 s
  • /tmp/claude-update.log appended to instead of overwritten, with a UTC
    timestamp per run
  • last 10 lines of the log tailed into the addon log on update failure
  • pymodbus / pyserial removal
  • a CI workflow (lint, hadolint advisory, boot-script bash -n /
    shellcheck, docker build smoke + boot-script smoke against a stub
    /data/options.json)

Will cut 1.2.67 once CI is green.

Yeah, I am not sure why it is there in the first place. For my repo it was inherited from the original file. I have removed it for now. Let me know if something breaks.