[BUG] Desktop SSH Remote: ccd-cli download picks musl build on glibc hosts → "is not runnable" (linux-amd64 mapped to linux-x64-musl)

Resolved 💬 2 comments Opened Jun 22, 2026 by hartwaretotal Closed Jun 26, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Preflight Checklist:

I have searched existing issues and this hasn't been reported yet. This is a single bug report. I am using the latest version (Desktop 1.14271.0).
Platform / Environment:

App: Claude Desktop 1.14271.0 (build c8f4d8), Windows. Remote: Debian 12 (Bookworm), glibc 2.36, x86_64, Plesk-managed vhosts. Feature: Code tab, SSH remote connection. ccd-cli version attempted: 2.1.181.
What's Wrong?
When connecting the Desktop app's Code tab to a Debian/Ubuntu (glibc) host over SSH, the bootstrap fails with: "Failed to install Claude CLI: installed cli at /var/www/vhosts/<domain>/.claude/remote/ccd-cli/2.1.181 is not runnable".
The srv/server transport binary deploys and runs fine. Only the ccd-cli binary fails. The directory ends up empty after the failed install, so there is no leftover file to inspect from the UI. The error message is the only signal.
Root cause (confirmed):
The app downloads the musl build of ccd-cli onto a glibc host. The downloaded binary is linked against musl: interpreter /lib/ld-musl-x86_64.so.1. Running it on the glibc host fails relocation: "Error relocating ./ccd-2.1.181: statx: symbol not found". The app classifies this as "not runnable" and wipes the directory.
Platform detection is the culprit. The app's own logs identify the host only as linux-amd64: "[BinaryDeployment] Remote: home=..., platform=linux-amd64, shell=posix" and map that to linux-x64-musl. Across the logs there are 5113 occurrences of linux-amd64 and 3081 of linux-x64-musl, and zero of linux-x64 (the glibc variant). The app never selects the glibc build for an amd64 Linux host.
By contrast, the official install.sh does this correctly. It probes for musl before choosing the variant: it sets arch=x64 for x86_64/amd64, then checks whether /lib/libc.musl-x86_64.so.1 exists or whether "ldd /bin/ls" reports musl, and only then sets platform=linux-x64-musl; otherwise it uses platform=linux-x64.
The release CDN does publish both variants for 2.1.181. Both linux-x64 and linux-x64-musl return HTTP 200, and the linux-x64 checksum matches the signed manifest.json. So the correct binary exists; the app just doesn't request it.
Steps to Reproduce:

Have a Debian/Ubuntu (glibc) host reachable via SSH key auth.
Desktop app, Code tab, add SSH remote to that host, pick a project directory.
Send any message.
Observe: "Failed to install Claude CLI: ... ccd-cli/<ver> is not runnable".

Expected:
The app should probe glibc vs musl on the remote (as install.sh does) and download linux-x64 for glibc hosts, only falling back to linux-x64-musl when musl is actually present.
Workaround:
Manually place the verified glibc build at the expected path, owned by the connecting SSH user. Download from https://downloads.claude.ai/claude-code-releases/<ver>/linux-x64/claude into ~/.claude/remote/ccd-cli/<ver> and chmod 755 it. The app then finds the runnable binary and starts the session. This must be redone for each new ccd-cli version until the platform detection is fixed.

What Should Happen?

When deploying ccd-cli to a Linux remote over SSH, the app should detect the host's libc (glibc vs musl) the same way the official install.sh does, rather than mapping every linux-amd64 host to the musl build.
Concretely, after resolving the architecture to x64, the app should probe the remote for musl (for example by checking whether /lib/libc.musl-x86_64.so.1 exists or whether "ldd /bin/ls" reports musl). If musl is present, download linux-x64-musl; otherwise download the glibc build linux-x64.
On a glibc host (Debian, Ubuntu, RHEL, etc.) the app should therefore download linux-x64, which runs correctly, and the Code session should start normally without any manual intervention.
Additionally, when the downloaded ccd-cli binary fails its runnability check, the app should surface the underlying error (for example the dynamic-loader / relocation failure such as "statx: symbol not found") instead of only reporting "is not runnable" and silently wiping the directory. The current behavior gives the user no actionable information and leaves no artifact to inspect.

Error Messages/Logs

Hier der Text für das Feld „Error Messages/Logs" als reiner Fließtext zum Reinkopieren. Ich habe die Diagnose-Belege zusammengestellt, die wir erarbeitet haben:

App error (Code tab, on connect):
Failed to install Claude CLI: installed cli at /var/www/vhosts/<domain>/.claude/remote/ccd-cli/2.1.181 is not runnable
Platform detection in the app logs (ssh/main logs):
[BinaryDeployment] Remote: home=/var/www/vhosts/<domain>, platform=linux-amd64, shell=posix, binVer=claude-ssh <hash> (built 2026-06-09T21:51:06Z)
Occurrence counts across the logs (confirming the mapping):

linux-amd64: 5113

linux-x64-musl: 3081

linux-x64: 0
Downloaded ccd-cli binary type (file output) — note the musl interpreter:
ccd-2.1.181: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-x86_64.so.1, BuildID[sha1]=..., not stripped
Result of running that binary on the glibc host:
Error relocating ./ccd-2.1.181: statx: symbol not found
Host libc (glibc, not musl):
ldd (Debian GLIBC 2.36-9+deb12u14) 2.36
Ruled out as causes (all verified clean on the host):

Mount is not noexec: findmnt reports rw,relatime on the ccd-cli path; an exec test (chmod +x on a small script in the same directory, run as the connecting user) returns EXEC_OK.
No disk/quota issue: 6.3 TB free on the partition.
zstd present and working: zstd v1.5.4 plus libzstd.so.1; the downloaded .zst archive passes "zstd -t" and decompresses cleanly to the full 227 MB binary.
The srv/server transport binary (a statically linked Go binary) deploys and runs fine on the same host; only ccd-cli fails.

CDN cross-check (the correct glibc build exists and is published):

https://downloads.claude.ai/claude-code-releases/2.1.181/linux-x64/claude returns HTTP 200, and its SHA256 matches the linux-x64 checksum in the signed manifest.json.
https://downloads.claude.ai/claude-code-releases/2.1.181/linux-x64-musl/claude also returns HTTP 200 (this is the variant the app incorrectly selects).

Steps to Reproduce

  1. Prepare a Debian or Ubuntu host (glibc-based, x86_64) reachable over SSH with key-based authentication. In my case it is a Plesk-managed server, Debian 12, glibc 2.36, and the connecting user is a per-domain system user whose home is under /var/www/vhosts/<domain>.
  2. Open the Claude Desktop app (1.14271.0) on Windows and go to the Code tab.
  3. Add an SSH remote connection to that host: enter host, port 22, the SSH user, and the key. Select a project directory on the remote.
  4. Confirm the status bar shows the connection (user@host and the project path) — it looks connected.
  5. Send any message in the Code session, for example "run pwd and ls".
  6. Observe the failure: "Failed to install Claude CLI: installed cli at /var/www/vhosts/<domain>/.claude/remote/ccd-cli/<version> is not runnable". The session never starts.
  7. Inspect the remote: the .claude/remote/srv/server transport binary is present and runs fine, but the .claude/remote/ccd-cli/<version> directory is empty (the failed binary was wiped). Watching the directory during a reconnect shows the app downloading <version>.zst (compressed ccd-cli), which grows to completion and is then removed when the post-download runnability check fails.
  8. Confirm the cause: if you capture the .zst before it is wiped and decompress it, "file" reports the binary uses interpreter /lib/ld-musl-x86_64.so.1 (a musl build), and running it on the glibc host fails with "Error relocating: statx: symbol not found".

Claude Model

Opus

Is this a regression?

Yes, this worked in a previous version

Last Working Version

Unknown / cannot pinpoint exactly. Failed installs wipe the ccd-cli directory and leave no artifact, so the precise version where the musl build was first selected can't be determined from the host. Last confirmed-working glibc deploys on this host were ccd-cli 2.1.121 and 2.1.128 (working sessions in the logs); locally retained binaries up to 2.1.177 were runnable glibc ELF executables. Confirmed broken at ccd-cli 2.1.181 with Desktop app 1.14271.0.

Claude Code Version

2.1.181 (ccd-cli, deployed via Desktop app SSH remote). Desktop app: 1.14271.0 (build c8f4d8), Windows.

Platform

Other

Operating System

Ubuntu/Debian Linux

Terminal/Shell

Windows Terminal

Additional Information

Für das Feld „Additional Information" als reiner Fließtext:

Scope: this affects every glibc-based Linux host connected as a Desktop SSH remote, not a single machine. On the same server I have multiple Plesk vhosts (each with its own system user), and all of them hit the identical failure once ccd-cli updates to the musl-only deployment. The workaround (manually placing the linux-x64 glibc build, owned by the connecting user) has to be repeated per domain and per version.
Severity: this completely blocks the Code-tab SSH remote feature on Debian/Ubuntu hosts. There is no in-app indication that a manual step is required, and because the failed install wipes the directory, a non-technical user has no way to diagnose or recover.
Suggested fix: reuse the libc-probing logic that already exists in the official install.sh (check for /lib/libc.musl-x86_64.so.1 or "ldd /bin/ls | grep musl") in the BinaryDeployment path, so linux-amd64 glibc hosts receive linux-x64 instead of linux-x64-musl. Both variants are already published on the CDN, so this is purely a client-side selection bug — no new artifacts need to be built.
Secondary request: improve the error surface. "is not runnable" with no detail and an immediately wiped directory makes this very hard to diagnose. Logging the loader/relocation error (e.g. "statx: symbol not found") and keeping the failed binary for inspection would have made the root cause obvious.
Related: this is the same BinaryDeployment / ccd-cli SSH-remote path discussed in issue #46845 (first-run wizard crash), but the failure mode here is distinct — it is a libc-variant mismatch, not the interactive-wizard issue.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗