docs: shorten windows remote startup guidance

This commit is contained in:
Jonathan Liebig
2026-10-28 02:07:48 +01:00
parent 5c6ff3c13e
commit 27b2716fbb
5 changed files with 22 additions and 18 deletions
@@ -49,21 +49,15 @@ For internal testing, `HERDR_MANIFEST_URL` can point the installer at a custom m
Local persistent sessions continue running after the client detaches or its terminal window closes. Servers and pane processes launched through Windows OpenSSH also survive logout; run `herdr` again to reconnect.
When SSH starts a missing server, Herdr uses an ordinary signed-in Windows session belonging to the same account. This lets tools use that login's desktop and sandbox context. If no such login exists, startup reports **Waiting for Windows sign-in** and does not start a server. Sign in to the Windows host with the same account: saved connections retry automatically, and an interactive `herdr --remote` stays open and retries before opening the TUI. A disconnected but still signed-in Windows session remains eligible. If several logins belong to the account, start Herdr in the intended login first. Existing servers and their panes stay in their current session, including servers already running in Session 0.
SSH cold starts use a signed-in Windows session of the same account. Without one, `herdr --remote` waits and saved connections retry automatically. Existing servers and panes keep running in their current session.
While an interactive command waits, **Esc** or **Ctrl+C** cancels. **F** deliberately starts in the SSH session (normally Session 0) for that attempt; the prompt warns that this may break Codex sandbox, computer use and desktop tools. This choice does not change the host's config. Saved connections never prompt or force startup. Waiting retries use normal SSH authentication; authentication or other startup failures are reported rather than treated as a missing login. Keyboard choices are handled between SSH operations, so an in-flight SSH request retains its usual latency. Non-terminal commands report the sign-in requirement without prompting.
Waiting and the one-attempt force choice require an updated Windows host binary. Older compatible running servers remain attachable; for an older stopped host, update Herdr on the host or start it from the Windows desktop first.
For a host that deliberately runs without a Windows sign-in, opt into SSH-context startup in the **Windows host's** `%APPDATA%\herdr\config.toml` (or its existing `HERDR_CONFIG_PATH` / `XDG_CONFIG_HOME` override):
While waiting, press **F** for a one-time Session 0 start, where Codex sandbox, computer use and desktop tools may fail; **Esc** or **Ctrl+C** cancels. To allow startup without sign-in by default, add this to the **Windows host's** `%APPDATA%\herdr\config.toml`:
```toml
[server]
allow_headless_remote_start = true
```
This Windows-only setting is false by default and is read on each cold start with no eligible login. Missing, unreadable or invalid config cannot enable automatic fallback; unknown config fields are tolerated. Config diagnostics remain visible even when you deliberately force a start. The fallback may lack Codex sandbox or desktop support. It does not bypass account, session or privilege checks, resolve multiple-login ambiguity, or retry a failed or uncertain desktop launch in Session 0. Local startup and already-running servers are unaffected.
Elevated Windows servers require an administrator client by default, including servers started through an elevated SSH login. Ordinary servers accept clients from ordinary and administrator terminals belonging to the same account; attaching never changes the server's privileges.
To deliberately share elevated sessions with ordinary clients, set:
@@ -20,7 +20,7 @@
"key": "server.allow_headless_remote_start",
"type": "boolean",
"default": "false",
"description": "Windows only: allow a remote cold start in the SSH session when no signed-in Windows session belongs to the same account. By default saved connections retry and interactive --remote waits with a deliberate one-attempt force choice. This fallback may break Codex sandbox, computer use and desktop tools. Existing servers, multiple-login ambiguity and account/session/privilege checks are unchanged. Read on each no-login cold start from the host config."
"description": "Windows only: allow remote startup without a same-account Windows sign-in, where Codex sandbox, computer use and desktop tools may fail."
},
{
"key": "server.allow_unelevated_clients",
+2 -2
View File
@@ -225,8 +225,8 @@ const DEFAULT_CONFIG: &str = r##"# herdr configuration
# Size of the virtual terminal used when no client is attached.
# Attached clients always use their own terminal size.
[server]
# Windows only: allow SSH-context startup when this account is not signed in.
# Codex sandbox and desktop tools may be unavailable in that context.
# Windows only: allow remote startup without Windows sign-in.
# Codex sandbox, computer use and desktop tools may fail.
# allow_headless_remote_start = false
# Windows only: allow ordinary same-account clients to control an elevated server.
# Requires a server restart.
+4 -2
View File
@@ -185,7 +185,7 @@ pub(crate) fn launch_remote_server_daemon_command(
let session = match sessions.as_slice() {
[] => {
require_headless_remote_start(allow_headless)?;
eprintln!("No signed-in Windows session is available. Starting Herdr in the SSH session; Codex sandbox and desktop tools may be unavailable.");
eprintln!("Starting Herdr in the SSH session; Codex sandbox, computer use and desktop tools may fail.");
tracing::warn!("No signed-in Windows session; starting remote server in the SSH session");
return super::launch_server_daemon_command(command);
}
@@ -255,7 +255,9 @@ pub(crate) struct WindowsSignInRequired;
impl std::fmt::Display for WindowsSignInRequired {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str("Waiting for Windows sign-in. Sign in to this host with the same Windows account. Saved connections retry automatically; interactive herdr --remote can wait or offer a deliberate Session 0 start. For intentional headless startup, set server.allow_headless_remote_start = true in this host's config.")
formatter.write_str(
"Waiting for Windows sign-in. Sign in on the Windows host with the same account.",
)
}
}
+13 -5
View File
@@ -2234,14 +2234,17 @@ fn ensure_windows_remote_server_started(ssh: &RemoteSsh, remote: &RemoteHerdr) -
},
|| {
if !io::stdin().is_terminal() {
return Err(io::Error::new(io::ErrorKind::WouldBlock, "Waiting for Windows sign-in. Sign in to the host with the same Windows account, or run herdr --remote from an interactive terminal to choose a Session 0 start."));
return Err(io::Error::new(io::ErrorKind::WouldBlock, "Waiting for Windows sign-in. Sign in on the Windows host with the same account."));
}
if !announced {
eprintln!("The Windows account on {} is not signed in. Waiting for Windows sign-in; Herdr will retry automatically.", ssh.destination());
eprintln!(
"This Windows account is not signed in on {}. Waiting for sign-in...",
ssh.target()
);
eprintln!(
"Forcing Session 0 may break Codex sandbox, computer use and desktop tools."
);
eprintln!("F: force Session 0 for this attempt · Esc/Ctrl+C: cancel · otherwise keep waiting");
eprintln!("F: force Session 0 once · Esc/Ctrl+C: cancel");
announced = true;
}
poll_windows_sign_in_choice()
@@ -2259,14 +2262,19 @@ fn prepare_windows_remote_start(
return Ok(());
}
if !supports_start()? {
return Err(io::Error::new(io::ErrorKind::Unsupported, "This Windows host needs an updated Herdr to wait for sign-in or choose Session 0. Update Herdr on the host, or start it from the Windows desktop, then reconnect."));
return Err(io::Error::new(
io::ErrorKind::Unsupported,
"Update Herdr on the Windows host, or start it from the Windows desktop and reconnect.",
));
}
let mut allow_headless = false;
loop {
match start(allow_headless)? {
RemoteStartStatus::Ready => return Ok(()),
RemoteStartStatus::WindowsSignInRequired if allow_headless => {
return Err(io::Error::other("remote host still requires Windows sign-in after the explicit Session 0 request"));
return Err(io::Error::other(
"The Windows host did not accept the Session 0 start.",
));
}
RemoteStartStatus::WindowsSignInRequired => allow_headless = choose_force()?,
}