fix: detect actual home directory for SFTP auto-open - #461
Conversation
Query the remote server for the real home directory using two methods:
1. SSH exec `echo ~` — works for any user regardless of home path
2. SFTP realpath('.') — fallback, SFTP cwd is typically home dir
Falls back to the previous hardcoded /home/{username} candidates if
both methods fail. This fixes SFTP auto-open sidebar not navigating
to the correct directory for users with non-standard home paths
(e.g. /usr/home, /export/home, custom paths).
Fixes #458
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ad15d8ceb5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const statSftp = bridge?.statSftp; | ||
| if (statSftp) { |
There was a problem hiding this comment.
Preserve home-path fallback when statSftp is missing
If getSftpHomeDir is unavailable/fails and the bridge does not expose statSftp, this path now skips all candidate checks and leaves startPath at /. Before this change, the else branch still probed /home/{username} and /root via listSftp, so non-root sessions could still auto-open in a home directory. Since statSftp is explicitly optional in global.d.ts, this is a real regression for optional/older bridge implementations and some test/mocked environments.
Useful? React with 👍 / 👎.
Preserve the original fallback behavior for bridges that don't expose statSftp — probe candidate directories via listSftp instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@codex review |
1 similar comment
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3db9b0aa26
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const sshClient = client.client; | ||
| if (sshClient && typeof sshClient.exec === "function") { | ||
| try { | ||
| const result = await execSshCommand(sshClient, "echo ~"); |
There was a problem hiding this comment.
Time-box the
echo ~ probe before falling back
getSftpHomeDir now awaits execSshCommand(sshClient, "echo ~") before trying SFTP realpath('.'), but this exec path has no timeout and only falls through on exceptions. On hosts where non-interactive shell startup hangs (for example a shell init script that reads stdin or a forced command that never exits), this promise never settles, so SFTP auto-open can block indefinitely instead of reaching the existing fallback logic.
Useful? React with 👍 / 👎.
Prevent indefinite blocking when the remote shell init hangs or a forced command never exits. Falls through to SFTP realpath after timeout. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 34ab6c0e98
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const result = await Promise.race([ | ||
| execSshCommand(sshClient, "echo ~"), | ||
| new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), 5000)), | ||
| ]); |
There was a problem hiding this comment.
Abort timed-out home probe commands
When the 5s timeout wins, Promise.race rejects but the in-flight execSshCommand("echo ~") is never cancelled, so that SSH channel can remain open indefinitely. This is most likely on the same hosts with blocking shell init scripts called out in the comment, and it can consume session slots (MaxSessions) for the lifetime of the connection and cause later channel opens to fail. Close/terminate the exec stream when the timeout path is taken.
Useful? React with 👍 / 👎.
| if (absPath) { | ||
| return { success: true, homeDir: absPath }; |
There was a problem hiding this comment.
Treat root realpath result as non-authoritative
The realpath('.') fallback is accepted unconditionally, so a returned '/' is treated as the user's home and bypasses the legacy /home/${username} probe. On servers where exec is disabled and SFTP starts in /, this regresses non-root users to opening root instead of their actual home directory. Consider treating '/' as ambiguous for non-root users and continuing to the candidate fallback chain.
Useful? React with 👍 / 👎.
- Close/destroy the SSH exec stream when the 5s timeout fires to
avoid leaking session slots (MaxSessions).
- Treat SFTP realpath('.') returning '/' as non-authoritative so
non-root users fall through to the candidate probe chain instead
of incorrectly opening at root.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@codex review |
|
Codex Review: Didn't find any major issues. Bravo. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Summary
/home/{username}echo ~— reliable for any userrealpath('.')— SFTP cwd is typically the home dir/home/{username}and/rootcandidates (unchanged fallback)Root cause
The SFTP auto-open sidebar assumed all non-root users have their home at
/home/{username}, which fails for:/usr/home)/export/home)/var/lib/...)Fixes #458
Test plan
/home/userpath — should still work/root🤖 Generated with Claude Code