Repository navigation
⚡️ Drop the compiler, persist Claude Code, pull upstream fixes - #1239
Merged
Merged
Conversation
`build-essential` and `python3-dev` were installed and purged again in the same layer, so they existed purely to compile Python packages while `pip install` ran. Installing them means dpkg unpacks and configures some 50 extra packages, which on aarch64 happens under QEMU emulation and is a large part of the ~290s dpkg phase. Drop both. Their absence is the guard: a dependency that needs to be compiled now fails the build loudly. `--only-binary=:all:` would be the stricter version of the same idea, but it also rejects pure-Python source distributions that install fine without a compiler, so it is left out. `wget` and `git-crypt` lost their version constraints in #1238 because neither the unquoted nor the quoted `pkg>=version` spelling reaches apt. `apt-get satisfy` does take relational constraints, so use it and give them back the lower bounds #1224 asked for — git-crypt carries a different binNMU revision per architecture (+b1 on amd64, +b2 on arm64), which an exact pin cannot express. A second Renovate manager tracks the `"pkg (>= version)"` spelling, so both are back on the dashboard. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pwumst3pLFGsbbzLSxYQMv
Claude Code is installed into the image with the official installer and linked into PATH, so `claude` works in every terminal. The service now exports CLAUDE_CONFIG_DIR=/data/claude, and the user init creates that folder and migrates a login left behind in ~/.claude or ~/.claude.json, so logins and settings survive restarts and updates. Both the persistence and the migration follow upstream's app-vscode. Unlike everything else in this image, Claude Code is not version-pinned: the installer is the only documented install path and it does not expose a pinning interface that could be verified. It also updates itself at runtime, into the container filesystem rather than /data, so a build-time pin would say little about what is actually running. Fixes pulled from upstream app-vscode: - The `find` cleanup bound its `-exec` to the last `-o` branch only, so only *.pyo files were ever removed, never the test, tests and __pycache__ directories it lists. - `01-vs-mysql` created /root/.config but writes the client config to /etc/mysql/conf.d/service.cnf, which it never created. - `01-vs-user` linked ~/.ssh with `ln -sn`; when ~/.ssh exists as a real directory the link lands inside it as ~/.ssh/.ssh. It now clears that case, cleans up the nested link and uses `ln -sfn`. - `01-vs-mosquitto` linked with plain `ln -s`, which fails on a re-run and reported nothing. Now `ln -sf` with a warning on failure. - `code-server/finish` treated a stop by signal as a crash and never propagated an exit code to the container. It now reports the code, halts on SIGTERM and lets s6 restart only on a real crash. - `code` is a wrapper so files open in the running editor from a terminal, `ha` gets its zsh completion registered, and the esphome file association matches nested folders. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pwumst3pLFGsbbzLSxYQMv
Installing Claude Code into the image is dropped again; what stays is the persistence, which is what upstream's app-vscode does. Users install the `Anthropic.claude-code` extension themselves from the Extensions view. It is published on Open VSX, the registry code-server uses for extensions installed from inside the editor, and it carries its own `claude` binary, so nothing has to be baked into the image. The service keeps exporting CLAUDE_CONFIG_DIR=/data/claude and the user init keeps creating and migrating that folder, so the login survives restarts and updates either way. The documentation follows: the app no longer claims to ship Claude Code, and DOCS.md explains installing the extension, why signing in has to happen from a terminal behind ingress, and where the bundled binary sits for anyone who wants it on PATH. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pwumst3pLFGsbbzLSxYQMv
elcajon
marked this pull request as ready for review
September 18, 2026 08:45
elcajon
enabled auto-merge (squash)
September 18, 2026 08:45
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Proposed Changes
Dropping the compiler
build-essentialandpython3-devwere installed and purged again inside thesame layer, so they existed purely to compile Python packages during
pip install. Both are gone; their absence is the guard, since a dependencythat needs compiling now fails the build loudly.
Measured, cold cache both times:
Only the amd64 number is worth trusting: repeated aarch64 runs of the same tree
came in at 9:29 and 11:14, so QEMU throughput varies by more than this change
moves the needle there.
One behavioural change worth knowing:
crcmod,esptoolandpaho-mqtthaveno aarch64 wheels and are built from sdists — that was already true before this
PR. They build fine without a compiler because the builds are pure Python, but
crcmodno longer builds its optional C accelerator (_crcfunext) and fallsback to the Python implementation. That affects checksum speed when flashing via
esptool, nothing else.
Claude Code configuration is persisted
Claude Code is not shipped in the image; users install the
Anthropic.claude-codeextension from the Extensions view, which is publishedon Open VSX and carries its own
claudebinary.What this app adds is persistence, following upstream
(hassio-addons/app-vscode#1129): the service exports
CLAUDE_CONFIG_DIR=/data/claude, and the user init creates that folder andmigrates a login left behind in
~/.claudeor~/.claude.json, so logins andsettings survive restarts and updates. DOCS.md explains the installation, why
signing in has to happen from a terminal behind ingress, and where the bundled
binary sits for anyone who wants it on
PATH.Version constraints
wgetandgit-cryptlost their lower bounds in #1238: unquoted,wget>=1.25.0-2is a shell redirection; quoted,apt-get installsplits at the=and looks for a package calledwget>.apt-get satisfydoes takerelational constraints, so they now read
which is what #1224 wanted — git-crypt carries a different binNMU revision per
architecture (
+b1on amd64,+b2on arm64), so an exact pin cannot cover both.A second Renovate manager matches the
"pkg (>= version)"spelling; verifiedagainst the Dockerfile, 23 exact pins on the existing manager and 2 constraints
on the new one.
Fixes pulled from upstream app-vscode
findcleanup bound its-execto the last-obranch only, so only*.pyofiles were ever removed — never thetest,testsand__pycache__directories it lists.
01-vs-mysqlcreated/root/.configbut writes the client config to/etc/mysql/conf.d/service.cnf, a directory it never created.01-vs-userlinked~/.sshwithln -sn; when~/.sshexists as a realdirectory the link lands inside it as
~/.ssh/.ssh. It now clears that case,cleans up the nested link and uses
ln -sfn(Fix SSH key symlink creating nested .ssh directory hassio-addons/app-vscode#1098).01-vs-mosquittolinked with plainln -s, which fails on a re-run andreported nothing. Now
ln -sfwith a warning.code-server/finishtreated a stop by signal as a crash and never propagatedan exit code to the container. It now reports the code, halts on SIGTERM and
lets s6 restart only on a real crash.
codewrapper so files open in the running editor from a terminal,hagetsits zsh completion registered, and the esphome file association matches
nested folders.
Deliberately not pulled, as discussed: the
config_pathoption and/configasthe workspace,
hassio_role: manager, thepackages/init_commandsoptions(this app has custom services instead), the
user-bundles.dlayout,python3-venvand/etc/motd(ha bannercovers it).Verification
hadolint 2.5.0, 2.8.0 and 2.14.0 clean; shellcheck clean on every changed
script, with no new findings;
settings.jsonvalid; the Renovate regexes runagainst the Dockerfile; doc link references resolved both ways and added lines
within the 80-column limit. Both architectures built green on the previous two
heads.
Related Issues
Follow-up to #1238; restores the constraint intent from #1224.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Pwumst3pLFGsbbzLSxYQMv