From af7fc0aca6f7824ebadbcd21b46f17f17ac23fcf Mon Sep 17 00:00:00 2001 From: Serge Gatezh <2880401+gatezh@users.noreply.github.com> Date: Mon, 8 Jun 2026 12:37:01 -0600 Subject: [PATCH] fix(claude-code): install openssh-client for SSH-format commit signing The shared `base` stage installs packages with --no-install-recommends, which drops git's Recommends on ssh-client (provided by openssh-client). The image therefore ships without ssh-keygen, so any container whose gitconfig uses SSH-format commit signing (gpg.format=ssh + commit.gpgsign=true, commonly copied in by VS Code's dev.containers.copyGitConfig) fails to commit: error: cannot run ssh-keygen: No such file or directory Add openssh-client to the base apt block so both the default and sandbox targets get ssh-keygen/ssh/ssh-add. It must live in base: the sandbox firewall blocks deb.debian.org, so it can't be apt-installed at runtime (same reasoning as chromium). openssh-client hard-depends on libfido2, so FIDO2 hardware keys (YubiKey sk-ssh-ed25519) sign too, even under --no-install-recommends. Closes #110 --- claude-code/.devcontainer/Dockerfile | 8 ++++++++ claude-code/README.md | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/claude-code/.devcontainer/Dockerfile b/claude-code/.devcontainer/Dockerfile index a20d18f..a98c356 100644 --- a/claude-code/.devcontainer/Dockerfile +++ b/claude-code/.devcontainer/Dockerfile @@ -55,6 +55,13 @@ ARG GIT_DELTA_VERSION=0.18.2 # - git: version control # - jq: JSON processing (firewall script, onboarding patch) # - less: pager for git delta output +# - openssh-client: provides ssh-keygen, needed for SSH-format commit signing +# (gpg.format=ssh + commit.gpgsign=true, copied in via VS Code's +# dev.containers.copyGitConfig); also restores ssh/ssh-add. git only +# *Recommends* it, so --no-install-recommends drops it unless listed here. +# Hard-depends on libfido2, so FIDO2 hardware keys (YubiKey sk-ssh-ed25519) +# sign too. Must be in base: the sandbox firewall blocks deb.debian.org, so +# it can't be added at runtime (same reasoning as chromium). See issue #110. # - sudo: privilege escalation for firewall setup RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt/lists,sharing=locked \ @@ -67,6 +74,7 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ git \ jq \ less \ + openssh-client \ sudo # npm global directory with proper permissions for node user diff --git a/claude-code/README.md b/claude-code/README.md index 50e6fde..798a9e0 100644 --- a/claude-code/README.md +++ b/claude-code/README.md @@ -17,7 +17,7 @@ Projects consume these pre-built images and control their own tool versions via |-------|------|-----| | OS | `node:24-trixie-slim` + system packages | Node is needed during the build (Playwright, npm globals) | | Shell | Fish, Starship, fzf | Built-in syntax highlighting, autosuggestions, completions | -| Tools | git-delta, gh CLI, jq, nano, vim, wget, unzip, less, man-db, procps | Standard dev utilities | +| Tools | git-delta, gh CLI, jq, nano, vim, wget, unzip, less, man-db, procps, openssh-client | Standard dev utilities (`openssh-client` provides `ssh`/`ssh-keygen` — enables SSH-format commit signing) | | Mise | The tool manager itself (not the tools) | Projects run `mise install` at container creation for their tool versions | | rtk, ralphex | Always-latest from GitHub Releases | Dev infrastructure (like Claude Code) — no version pinning needed in projects | | Claude Code | npm global install | npm avoids rate limiting that affects the native installer in parallel CI builds |