Originally created by: kumaakh
Originally owned by: kumaakh
The out-of-band (OOB) password entry feature works correctly on GUI desktops, but produces a misleading \"❌ Password entry cancelled\" error when the user is on an SSH session or any headless environment where `$DISPLAY` / `$WAYLAND_DISPLAY` is unset — even though the underlying socket mechanism works fine in those environments.
On Linux, launchAuthTerminal (src/services/auth-socket.ts:334-441) tries to open a GUI terminal emulator in order: gnome-terminal → xterm → x-terminal-emulator. The user types their password in that new window, and it is delivered over a Unix domain socket (UDS) at ~/.apra-fleet/auth.sock.
| Environment | Behavior |
|---|---|
GUI desktop ($DISPLAY set) |
Auto-launches a terminal window ✅ |
| SSH/headless, no terminal emulators installed | Correctly falls back to a manual instruction ✅ |
| Windows desktop | Opens a new Command Prompt window ✅ |
| Environment | Current behavior | Expected behavior |
|---|---|---|
SSH/Linux, terminal emulators installed but $DISPLAY unset |
which gnome-terminal succeeds → spawn attempted → exits immediately → misleading "❌ Password entry cancelled" ❌ |
Skip GUI attempt, show actionable instructions |
| SSH/Windows | cmd.exe window spawned but appears on physical console, invisible to SSH user ❌ |
Detect no interactive desktop, show actionable instructions |
| Headless server (any OS), no display | Same bug ❌ | Same fix |
The UDS at ~/.apra-fleet/auth.sock is a filesystem object on the server — any process on that machine can reach it. No GUI is needed. Two patterns work:
The system shows:
"No graphical display. In a second terminal on this machine, run:
apra-fleet auth <actual-member-name>
Then return here — the password will be received automatically."
! operator in Claude CLI (preferred, eliminates second terminal)Claude CLI's ! prefix runs OS commands in the current shell session. The system could instead instruct:
"Run this in your current session:
! apra-fleet auth <actual-member-name>"*
The password input is masked (noecho) so the LLM does not see the secret — only the success/failure result. This is cleaner than opening a second terminal.
Caveat: needs verification that Claude CLI's ! forwards stdin interactively (required for masked password input).
apra-fleet auth my-server), not a <name> placeholder. The system knows the member name at this point.apra-fleet must be in PATH — it is (same shell environment as Claude CLI), but worth verifying in edge-case install configurations.Add a display-presence check before attempting GUI terminal emulators:
// Linux
function hasGraphicalDisplay(): boolean {
return !!(process.env.DISPLAY || process.env.WAYLAND_DISPLAY);
}
// Windows
function hasInteractiveDesktop(): boolean {
return process.env.SESSIONNAME === 'Console';
}
In launchAuthTerminal: if no graphical display is detected, skip the terminal emulator attempt and return a fallback with the actual member name substituted and ! apra-fleet auth <name> as the preferred action.
src/services/auth-socket.ts — launchAuthTerminal function (~line 334–441)
Originally posted by: kumaakh
Related: [#42] — the OOB terminal window on Windows also lacks paste support (Ctrl+V), Esc to cancel, and proper unblocking on window close. Both issues point to the same area of the OOB password entry UX needing a more robust cross-platform approach.
Related
Tickets:
#42Originally posted by: kumaakh
Correction to issue body: Windows does not use a Unix Domain Socket. The two IPC mechanisms are:
~/.apra-fleet/auth.sock(src/services/auth-socket.ts:10,35)\.\pipe\apra-fleet-auth-<username>(src/services/auth-socket.ts:33)The good news: Named Pipes on Windows are machine-scoped and accessible from any process on the server, including a second SSH session — same property as UDS on Linux. So the two-session pattern (or
! apra-fleet auth <name>in the same Claude CLI session) works on Windows SSH for the same reason.The root bug on Windows SSH remains the same:
launchAuthTerminalspawns acmd.exe /c start ...window (src/services/auth-socket.ts:418-419) which targets the physical desktop console, not the SSH session.Originally posted by: kumaakh
Correction on the
!operator suggestion:apra-fleetis not guaranteed to be in PATH on a remote SSH server. However,getAuthCommand()(src/services/auth-socket.ts:316-329) already resolves the correct invocation usingprocess.execPath(SEA build) orprocess.argv[0]+ absoluteindex.jspath (dev mode) — so the fallback message already contains the exact full command the user needs to run.The
!operator idea still holds, but the instruction to the user should be:Not a bare
apra-fleet auth <name>— that would only work ifapra-fleethappens to be in PATH.Originally posted by: kumaakh
!operator approach confirmed not viable.Tested
! ~/.apra-fleet/bin/apra-fleet auth <name>from Claude CLI: theauthcommand uses an interactive masked password prompt that requires a real TTY. Claude CLI's!operator provides no TTY, so the prompt receives empty input and immediately aborts with✗ Empty password. Aborting.Passing the password as a CLI argument also doesn't work — it is ignored.
Conclusions:
apra-fleetis installed at~/.apra-fleet/bin/apra-fleet, not in system PATH — the fallback message must show the full path, not a bareapra-fleet auth <name>getAuthCommand()already resolves to the full binary path viaprocess.execPath, so the fallback message content is already correct — it just needs to be surfaced in SSH environments instead of the misleading "cancelled" errorOriginally posted by: kumaakh
Technical direction: Add a graphical-display presence check before attempting to spawn terminal emulators on Linux and Windows.
In
src/services/auth-socket.ts, add two helpers:hasGraphicalDisplay(): returns true ifprocess.env.DISPLAYorprocess.env.WAYLAND_DISPLAYis set (Linux)hasInteractiveDesktop(): returns true ifprocess.env.SESSIONNAME === 'Console'(Windows — 'Services' or undefined means headless)In
launchAuthTerminal, on the Linux branch:hasGraphicalDisplay()before callingfindLinuxTerminal()memberNamesubstituted and! apra-fleet auth <memberName>as the preferred actionOn the Windows branch:
hasInteractiveDesktop()before spawningcmd.exe /c startThe fallback message must substitute the real member name — no placeholder text. The
memberNameparameter is available at the call site.Key file:
src/services/auth-socket.ts—launchAuthTerminal(~line 376) andfindLinuxTerminal(~line 361). Small targeted fix, no schema changes.Ticket changed by: kumaakh