Repository navigation
Conversation
The Linux release binary links GTK and WebKitGTK 4.1 through Tauri and is built against glibc 2.35, so it fails to load on RHEL 8 (glibc 2.28, no WebKitGTK 4.1) even for daemon and CLI commands. - Build agentdesktop-headless (daemon + CLI, no Tauri) in a manylinux_2_28 container (pinned by digest) for amd64 and arm64, attest it, and attach it to releases. - Add verify-linux-portability.sh to fail when the binary needs a glibc newer than 2.28 or links a library outside the base system set; run it in CI and release. - Move client socket resolution (AGENTDESKTOP_SOCKET, system socket, then the per-user socket) into agentdesktop-core so the headless CLI finds a user-mode daemon the same way the desktop binary does. - Document the headless binary and a systemd user unit for RHEL 8, WSL and VDI. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
The documented fresh-install service cannot start without a required configuration file that the setup instructions never prepare.
2 open issues
What changed in this PR
Adds a headless Linux release option for RHEL 8, WSL, and other hosts that cannot run the Tauri desktop binary.
Changes:
- Builds and attests amd64 and arm64 headless binaries targeting glibc 2.28, with portability checks in CI and releases.
- Shares daemon socket discovery between desktop and headless clients.
- Documents headless installation, user-mode service setup, and authentication.
| File | Description |
|---|---|
| README.md | Adds headless Linux installation and service instructions. |
| crates/core/src/lib.rs | Introduces shared client socket lookup. |
| crates/agentdesktop/src/main.rs | Uses the shared socket lookup. |
| crates/agent/src/bin/agentdesktop-headless.rs | Adds automatic socket discovery for CLI commands. |
| .github/workflows/release.yml | Describes headless assets in release notes. |
| .github/workflows/release-linux.yml | Builds, packages, and attests headless Linux binaries. |
| .github/workflows/ci.yml | Adds a headless Linux portability job. |
| .github/scripts/verify-linux-portability.sh | Checks glibc requirements and shared-library dependencies. |
Review effort: Balanced
|
|
||
| ```sh | ||
| curl -fLO https://github.com/agentdesktop-dev/agentdesktop/releases/latest/download/agentdesktop-headless-linux-amd64 | ||
| install -m 0755 agentdesktop-headless-linux-amd64 ~/.local/bin/agentdesktop |
There was a problem hiding this comment.
Fixed in 1aedf11: the install step now uses install -D, which creates ~/.local/bin when it is missing.
| Description=Agentdesktop daemon | ||
|
|
||
| [Service] | ||
| ExecStart=%h/.local/bin/agentdesktop daemon --user |
There was a problem hiding this comment.
Fixed in 1aedf11: the README now says that daemon --user needs ~/.config/agentdesktop/config.yaml (or the $XDG_CONFIG_HOME equivalent). It adds a step that copies examples/standalone/config.yaml there before you enable the unit.
|
thanks for the PR @jmcshane! can you check the comments? |
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
should use musl to avoid the glibc dep
…On Mon, Oct 26, 2026 at 7:54 AM James McShane ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In README.md
<#200 (comment)>
:
> +curl -fLO https://github.com/agentdesktop-dev/agentdesktop/releases/latest/download/agentdesktop-headless-linux-amd64
+install -m 0755 agentdesktop-headless-linux-amd64 ~/.local/bin/agentdesktop
+agentdesktop --version
+```
+
+Every `agentdesktop` command in this guide works with the headless binary. To
+keep a user-mode daemon running, create a systemd user unit at
+`~/.config/systemd/user/agentdesktop.service` (on WSL, first set
+`systemd=true` under `[boot]` in `/etc/wsl.conf`):
+
+```ini
+[Unit]
+Description=Agentdesktop daemon
+
+[Service]
+ExecStart=%h/.local/bin/agentdesktop daemon --user
Fixed in 1aedf11
<1aedf11>:
the README now says that daemon --user needs
~/.config/agentdesktop/config.yaml (or the $XDG_CONFIG_HOME equivalent).
It adds a step that copies examples/standalone/config.yaml there before
you enable the unit.
—
Reply to this email directly, view it on GitHub
<#200?email_source=notifications&email_token=AAEYGXIY52D5Z4WQCVZHAMT5V5QSLA5CNFSNUABKM5UWIORPF5TWS5BNNB2WEL2QOVWGYUTFOF2WK43UKJSXM2LFO4XTKNRVGQYDEMRVGAZKM4TFMFZW63VKON2WE43DOJUWEZLEUVSXMZLOOSWGM33PORSXEX3DNRUWG2Y#discussion_r4378709778>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAEYGXLV3ZIK3I57W6WVLGD5V5QSLAVCNFSNUABGKJSXA33TNF2G64TZHMYTGMJYG42DGMJUGA5US43TOVSTWNRQGE3DCNJUGA2DHILWAI>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
Replace the manylinux_2_28 (glibc 2.28) build with x86_64/aarch64 unknown-linux-musl targets on the standard Ubuntu runners. The binary no longer depends on the host's libc, and CI no longer needs a build container or pinned image digests. The portability check now verifies that the binary has no dynamic loader and no NEEDED libraries. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
@howardjohn refactored to musl |

Problem
The
agentdesktop-linux-*release binary does not start on RHEL 8 (and RHEL 8 under WSL2, as used on many virtual desktops), even fordaemonand CLI commands:The binary contains the Tauri UI, so the loader needs GTK and WebKitGTK 4.1 before
main()runs. It is also built on Ubuntu 22.04, so it needsGLIBC_2.34. RHEL 8 has glibc 2.28 and no WebKitGTK 4.1 (that arrived in RHEL 9), so installing packages cannot fix it.Change
The daemon and CLI already exist without Tauri as the
agentdesktop-headlessbin inagentdesktop-agent, but it was never released. This PR ships it:build-linux-headless-binariesjob buildsagentdesktop-headlessforx86_64-unknown-linux-muslandaarch64-unknown-linux-muslon the standard Ubuntu runners (musl-tools, no container). The result is a fully static binary with no glibc or other shared-library dependency, so it runs on any Linux. The binaries are attested with the existing Linux binaries and attached to the release asagentdesktop-headless-linux-{amd64,arm64}..github/scripts/verify-static-binary.shfails when the binary requests a dynamic loader (PT_INTERP) or has anyNEEDEDlibrary. It runs in the release job and in a new CI job, so a dependency that breaks static linking fails on the PR instead of at a user.--userdaemon throughAGENTDESKTOP_SOCKET, then the system socket, then$XDG_RUNTIME_DIR/~/.local/state. The headless binary only tried the system socket, so its CLI could not reach a user-mode daemon. The lookup moves toagentdesktop_core::client_socket_path()and both binaries use it.systemd=truenote), and how sign-in works without a local browser.No new dependencies and no code changes for musl: the native crates in the headless tree (aws-lc-sys, bundled SQLite, inotify) all build against musl. The headless binary has no GTK, WebKit, D-Bus, or OpenSSL dependency (TLS is rustls with aws-lc-rs).
An earlier revision of this PR built against glibc 2.28 in
manylinux_2_28. Review feedback suggested musl instead: it removes the glibc floor entirely and drops the container and image digests from CI.Testing
Build and portability
aarch64-unknown-linux-muslwith the CI recipe (Ubuntu 24.04,musl-tools, Rust 1.98) and in Alpine. Both produce a static binary with noPT_INTERPand noNEEDEDentries;verify-static-binary.shpasses on it and fails on a dynamic binary (/bin/ls). In an AlmaLinux 8 container (glibc 2.28) the musl binary runs--version, anddaemon --userwith the standalone example config reconciles the managed files, listens on the user socket, and, with the issuer pointed at Microsoft Entra ID, resolves DNS, fetches the OIDC discovery document over HTTPS (system CA store) and prints the authorization URL.manylinux_2_28for aarch64 and x86_64; the end-to-end test below used this build.cargo fmt --check,cargo clippy -D warnings(core and agent) and theagentdesktop-coretests pass. Theagentdesktopdesktop crate change is a rename to the shared function; CI covers its build because it needs WebKitGTK.End to end on a RHEL 8-class WSL desktop behind an LLM gateway (glibc 2.28 build)
To reproduce the reported environment, we built a short-lived Azure lab and deleted it after the test:
D4ds_v5, nested virtualization) with WSL 3.0.3 and the official AlmaLinux 8.10 WSL image (RHEL 8 ABI, glibc 2.28, no WebKitGTK 4.1). systemd was left off, which is the WSL default, as on the reporting user's machine./v1route to OpenAI withjwtAuthinstrictmode accepts only Microsoft Entra ID access tokens for the Agentdesktop app registration (v2.0 issuer, app audience, remote JWKS), and the gateway injects the OpenAI key upstream.llmGateway.urlpoints to the gateway, withauthentication.type: oidcagainst Entra andprograms.codex.useLlmGateway: true. Agentdesktop wrote Codex's provider (base_url = <gateway>/v1) with itself as the credential helper. No provider block was written by hand.Steps and results:
The released v0.3.0
agentdesktop-linux-amd64fails in the WSL distro with the missing-library errors above. This reproduces the report.The headless binary from this branch, installed as
~/.local/bin/agentdesktop, starts on the same distro with no missing libraries.agentdesktop daemon --userran in the foreground (no systemd). WSL has no browser, so the daemon printed the Entra sign-in URL. Opening it in Edge on the Windows host completed the OIDC flow through WSL's localhost forwarding to the daemon's127.0.0.1callback.Codex 0.164.0 (static musl build) in WSL sent requests through the gateway using the Agentdesktop-issued Entra token. Gateway access log, abbreviated:
GET /v1/models?client_version=0.164.0(×6)POST /v1/responses(×2)gpt-5.6-terraPOST /v1/responsesRequests with no token or a malformed token got 401.
Not covered here
workflow_dispatchrun ofReleasewithskip_github_release: truewould exercise them before the next tag.headless-linuxjob builds and checks it on this PR.mimalloccan be enabled for musl targets only./etc/hostsand DNS only (no SSSD/LDAP host lookups).HTTPS_PROXY, and the controller channel trusts onlycontroller.caCertificatePath. That is a separate change.🤖 Generated with Claude Code