Find the SSH agent and the default keys, the way ssh does - #13
Merged
Conversation
Reported as "I can't connect to any of my live servers", and reproducible against the real ~/.ssh/config: every host that declares no IdentityFile became `agent` authentication, and agent authentication demanded that SSH_AUTH_SOCK be exported. A desktop app is launched from a session that exports far less than a login shell, so those hosts failed with "No SSH agent is available" — in a terminal, on the same machine, all of them worked. Agent authentication now does both halves of what ssh(1) does. It finds a socket: SSH_AUTH_SOCK when set, because that is intent rather than a guess, then the sockets the common agents leave in XDG_RUNTIME_DIR. And it offers the default identities — id_ed25519, id_ecdsa, id_rsa, id_dsa, in ssh's own order — so a host with no configured key is not a host with no key. Only when neither turns anything up is it an error, and the message now says what was looked for. Two smaller things that make a path unusable in the same way: `~` in a key path was expanded in exactly one place in the tree, the ssh_config reader. A path typed into the New server dialog, or stored by either import command, kept its tilde and failed as `ENOENT ... open '~/.ssh/id_ed25519'` — a path that reads as plainly correct. It is now expanded where the key is read, so every source is covered, and both imports store it expanded too. `IdentityFile "/path with spaces/key"` is valid ssh_config. The parser kept the quotes, making the path a file that cannot exist. Verified against the real config with SSH_AUTH_SOCK unset — the exact condition that broke it. Before: "No SSH agent is available" on every agent host. After: the agent socket and ~/.ssh/id_ed25519 are both found and those hosts reach the network, where what is left is ordinary reachability from this box. `dev` still lists its home directory, 225 entries. 18 new tests. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTQ3RzTAey9nT6r1kbGBCd
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
"I can't connect to any of my live servers"
Reproducible against a real
~/.ssh/config. Probing five hosts with the shipping code:Every host that declares no
IdentityFilebecomesauthType: 'agent', and agent authentication demanded thatSSH_AUTH_SOCKbe exported. A desktop app is launched from a session that exports far less than a login shell — so those hosts failed in the window while all of them worked in a terminal on the same machine. The user had an agent running the whole time, at/run/user/1000/ssh-agent.socket; nothing ever looked there.Wiring that socket in by hand removed the auth error entirely and left only ordinary network state, which is what confirmed the diagnosis rather than assumed it.
The fix
Agent authentication now does both halves of what
ssh(1)does:SSH_AUTH_SOCKfirst, because that is intent rather than a guess, then the sockets common agents leave inXDG_RUNTIME_DIR(systemd'sssh-agent.socket, gnome-keyring, gcr,openssh_agent).id_ed25519,id_ecdsa,id_rsa,id_dsa, in ssh's own order. A host with no configured key is not a host with no key.Only when neither turns anything up is it an error, and the message now names what it looked for instead of naming an environment variable.
Two smaller things that break a path the same way
A tilde was expanded in exactly one place in the tree — the ssh_config reader. A key path typed into the New server dialog, or stored by either import command, kept its
~and failed asENOENT: no such file or directory, open '~/.ssh/id_ed25519'— an error naming a path that reads as plainly correct. It is now expanded where the key is read, so every source is covered, and both imports store it expanded.IdentityFile "/path with spaces/key"is valid ssh_config, and the parser kept the quotes, making the path a file that cannot exist. (Present in the config that prompted this, on thethunderhost.)Verified
Against the real config with
SSH_AUTH_SOCKunset — the exact condition that broke it.Before:
No SSH agent is availableon every agent host.After: the agent socket and
~/.ssh/id_ed25519are both found; those hosts reach the network, where what remains is reachability from this box (ECONNREFUSED, handshake timeouts) and one unknown host key, which in the app is the Trust dialog.devstill lists its home directory — 225 entries.pnpm test— 314 passed, 28 files (18 new)pnpm typecheck— cleanOne test earned its place immediately: passing
undefinedfor a uid silently triggered the parameter default, so "no uid" could not be expressed. The API now usesnullfor that.🤖 Generated with Claude Code
https://claude.ai/code/session_01GTQ3RzTAey9nT6r1kbGBCd