Skip to content

v1.5.5 - CLI-History

Latest

Choose a tag to compare

@gregorkrebs gregorkrebs released this 16 Aug 21:14
4a017c2

Added

  • CLI history: what was run over the CLI companion is now visible in the app. Every NeoSSHWinManager-cli.exe invocation against a saved connection is recorded and can be reviewed inside the GUI — both --exec calls (command, output, exit code) and interactive sessions (full screen transcript). A new "View CLI history" button in the connection details opens a dedicated panel (src/ui/cli_history_panel.py) listing entries newest first — a Session/Command badge, timestamp (start–end for sessions), the command line and its exit code, with the output collapsed until clicked so long histories stay scannable — plus "Download as .txt" for the complete history and "Clear history". UI strings ship in all six supported languages.
  • History entries are stored in a new encrypted cli_history table: command and output are encrypted with the same per-user key as connection passwords, never written in plaintext, and are capped at 500 entries per host (oldest pruned by insertion order) and 256 KB per entry to bound database growth. The CLI process never holds the GUI session's encryption key, so it hands the entry to the running GUI instance over the existing user-restricted IPC pipe (new cli_log action, same access-key check and per-PID rate limit as cli_connect), which does the encrypting and storing.
  • Interactive session transcripts are rendered the way the screen actually looked rather than dumped as a raw byte stream: backspace and DEL now delete the character to the left instead of leaving \x08 litter in the log after a typo, and a bare carriage return repositions the cursor instead of being treated as a newline — so progress bars (pip, apt, curl, docker pull, npm) show their end state instead of one line per redraw. ANSI/VT100 escape sequences are stripped. Recording is strictly best-effort and fully exception-swallowed; it can never affect the SSH session, its exit code, or its runtime.
  • NEOSSH_EXEC_TIMEOUT (seconds) sets an optional time limit for --exec; unset means no limit.

Fixed

  • SSHFS drives no longer disappear because their long-running process lost or blocked on GUI-owned debug pipes. Mounts now run in foreground mode with parent-independent standard handles, retain their process handle, and require a free drive letter that becomes stably available.
  • Disconnect now finds the exact SSHFS process through the bundled psutil dependency instead of the deprecated WMIC command, treats an already absent drive as success, and cancels stale Explorer label updates that could create ghost-drive entries.
  • The CLI tool always exited with code 0, even when nothing worked. launch_ssh_in_current_terminal() returned nothing and cli_main.py reported success unconditionally, so a failed connection, a rejected host key or a failed authentication was indistinguishable from a successful run — scripts calling the CLI could not detect failure at all. The function now returns an exit code, and --exec propagates the remote command's exit status (via recv_exit_status()) instead of discarding it.
  • --exec output was lost whenever the caller redirected stdout. Output was written to the CONOUT$ console screen buffer through WriteFile, which is not the process's stdout: NeoSSHWinManager-cli.exe --connect-cli … --exec "…" > out.txt reported success and produced an empty file. Non-interactive mode now writes exclusively to the real process streams, and the interactive path falls back to them if no valid console handle exists instead of writing into the void.
  • --exec aborted after 30 seconds. The hardcoded timeout was too short for anything substantial (test runs, npm install, backups) and cut execution off mid-command; ssh itself imposes no such limit. There is no default limit anymore — see NEOSSH_EXEC_TIMEOUT above.
  • --exec status messages ("Connecting to …") went to stdout and contaminated the command output that scripts parse; they now go to stderr, leaving stdout to the remote command alone. Execution errors with an empty str(e) — common for socket.timeout — no longer produce a bare "Error executing command:" with no cause, and a timeout now says so explicitly and points at NEOSSH_EXEC_TIMEOUT.
  • The IPC listener silently dropped any request larger than 64 KB. A single ReadFile against a message-mode pipe signals an oversized message with ERROR_MORE_DATA rather than an error, so the GUI just saw a truncated payload fail to parse and handled no request at all. The listener now drains the full message (with a 2 MB ceiling) and the pipe buffers were raised to 1 MB — required for cli_log entries carrying command output, and a latent bug for any future large request.