diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index d412575..0a2289d 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -22,16 +22,25 @@ Wails v2 desktop app: Go backend + HTML/CSS/JS frontend rendered in a native web **Go backend** (`internal/`): - `app/` — lifecycle bootstrap: opens SQLite, inits secret stores, wires everything together - `api/` — single `Service` struct bound to Wails; every public method is callable from JS as `window.go.api.Service.MethodName()` -- `sessions/` — manages concurrent protocol sessions; owns SSH/Telnet/RAW/GitHub client lifecycles +- `sessions/` — manages concurrent protocol sessions; owns SSH/Telnet/RAW/GitHub client lifecycles; handles auto-reconnect, login scripts, broadcast - `storage/` — SQLite repository (WAL mode) with embedded sequential migrations in `storage/migrations/` - `secrets/` — two-tier credential storage: OS keychain (preferred) → AES-256-GCM encrypted file vault (fallback) - `models/` — shared domain types and defaults; protocol configs are JSON-encoded in the DB -- `sshclient/`, `telnetclient/`, `rawclient/`, `githubclient/` — protocol implementations +- `sshclient/` — SSH client with agent, TOTP/2FA, and SOCKS5/HTTP proxy support +- `telnetclient/`, `rawclient/`, `githubclient/` — protocol implementations +- `sftpclient/` — SFTP file operations (browse, upload, download, rename, delete) +- `sshconfig/` — OpenSSH `~/.ssh/config` parser and importer +- `recording/` — asciicast v2 session recording and playback +- `exportimport/` — encrypted profile bundles (.nexus format) +- `updater/` — GitHub Releases update checker +- `knownhosts/` — SSH host key management +- `validation/` — profile and protocol validation +- `audit/` — timestamped audit logging **Frontend** (`frontend/`): - Plain HTML/CSS/JS — no framework, no bundler, no ES modules - `index.html` is the app shell; loads CSS then JS in strict order -- `src/js/` — 13 modules, each IIFE-wrapped, exporting to `window.NexusTerminal` +- `src/js/` — 18 modules, each IIFE-wrapped, exporting to `window.NexusTerminal` - `src/css/` — modular stylesheets; `tokens.css` defines all design tokens - Vendor libs (xterm.js, addons) live in `src/js/lib/` and `src/css/lib/` — auto-copied, gitignored @@ -69,9 +78,11 @@ The macOS webview silently blocks or breaks several standard web APIs. These con **Frontend patterns:** - Every JS file is IIFE-wrapped and exports to `window.NexusTerminal` namespace -- Script load order matters (defined in `index.html`) — utils → state → notifications → sidebar → tabs → terminal → profiles → raw → github → settings → commands → secrets → app +- Script load order matters (defined in `index.html`) — utils → state → notifications → sidebar → tabs → themes → terminal → profiles → raw → github → settings → commands → secrets → recordings → sftp → splitpane → snippets → app - DOM helpers: `createElement(tag, className, attrs)` from utils.js (supports `textContent`, `innerHTML`, `dataset`, `on*` event handlers) - Profile editor uses `_renderSection(title, fields)` pattern with `_field(type, name, label, value, opts)` helper for form generation +- Login script editor uses `_renderLoginScriptSection(prefix, steps)` for expect-style step lists +- TOTP section uses `_renderTOTPSection(profile)` with encrypted vault storage - `protocolColour()` returns CSS class names like `proto-ssh`; tab badges use `badge-ssh` class naming (different pattern) **CSS patterns:** diff --git a/README.md b/README.md index a7e9aa7..d4f1e3f 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Built with [Wails v2](https://wails.io/) (Go backend, HTML/CSS/JS frontend, [xte ### Feature Highlights -- ✅ SSH with password, public key, keyboard-interactive, and SSH agent authentication +- ✅ SSH with password, public key, keyboard-interactive, SSH agent, and TOTP/2FA - ✅ Telnet with option negotiation, encoding, and local echo - ✅ RAW TCP with text, hex, and split views - ✅ GitHub repository browser grouped by organisation @@ -17,6 +17,14 @@ Built with [Wails v2](https://wails.io/) (Go backend, HTML/CSS/JS frontend, [xte - ✅ Session recording and playback (asciicast v2) - ✅ Encrypted vault (AES-256-GCM + Argon2id) and OS keychain integration - ✅ Jump hosts, port forwarding, and SSH agent forwarding +- ✅ SOCKS5 and HTTP CONNECT proxy support for SSH +- ✅ Auto-reconnect with exponential backoff +- ✅ Auto-login scripts (expect-style send/wait sequences) +- ✅ Broadcast input — type into multiple sessions at once +- ✅ Snippet/command library for frequently-used commands +- ✅ Terminal search with regex and case-sensitivity toggles +- ✅ Right-click context menu on terminal +- ✅ Quick connect without saving a full profile - ✅ OpenSSH `~/.ssh/config` import - ✅ Encrypted profile export/import (`.nexus` format) - ✅ 8 built-in colour themes and command palette @@ -29,12 +37,13 @@ Built with [Wails v2](https://wails.io/) (Go backend, HTML/CSS/JS frontend, [xte 1. [Getting Started](#getting-started) 2. [Keyboard Shortcuts](#keyboard-shortcuts) 3. [Connection Types](#connection-types) -4. [Security](#security) -5. [Architecture](#architecture) -6. [Building & Testing](#building--testing) -7. [Data Locations](#data-locations) -8. [Troubleshooting](#troubleshooting) -9. [Licence](#licence) +4. [Power Features](#power-features) +5. [Security](#security) +6. [Architecture](#architecture) +7. [Building & Testing](#building--testing) +8. [Data Locations](#data-locations) +9. [Troubleshooting](#troubleshooting) +10. [Licence](#licence) --- @@ -61,6 +70,10 @@ make dev # launch with hot reload The first build may take a minute or two while dependencies are fetched. Once it's running you'll see the Nexus Terminal window appear — ready to create your first connection profile. +### Quick Connect + +If you just want to connect to a server without setting up a full profile, press **Cmd+Shift+Q** (macOS) or **Ctrl+Shift+Q** (Windows/Linux). Choose a protocol (SSH, Telnet, or RAW), enter the host and port, and you're connected immediately. The session won't be saved as a profile unless you choose to save it afterwards. + --- ## Keyboard Shortcuts @@ -80,6 +93,9 @@ All shortcuts use **Cmd** on macOS and **Ctrl** on Windows/Linux. | Cmd + Shift + D | Split pane vertically | | Cmd + Shift + E | Split pane horizontally | | Cmd + Shift + R | Toggle session recording | +| Cmd + Shift + B | Toggle broadcast input mode | +| Cmd + Shift + S | Open snippet library | +| Cmd + Shift + Q | Quick connect | | F11 | Toggle fullscreen (Windows/Linux) | --- @@ -91,9 +107,13 @@ All shortcuts use **Cmd** on macOS and **Ctrl** on Windows/Linux. Full-featured SSH client with support for: - **Authentication** — password, public key, keyboard-interactive, SSH agent, and agent forwarding +- **TOTP/2FA** — auto-fill time-based one-time passwords during keyboard-interactive auth (configure a TOTP secret in the profile editor) - **Jump hosts** — connect through one or more bastion servers (multi-hop) - **Port forwarding** — local, remote, and dynamic (SOCKS) tunnels -- **SFTP** — built-in file browser that slides open as a right-side overlay panel +- **Proxy support** — route connections through SOCKS5 or HTTP CONNECT proxies (with optional authentication) +- **SFTP** — built-in file browser that slides open as a right-side overlay panel (click the 📁 icon on the tab) +- **Auto-login scripts** — define expect-style send/wait sequences to automate login flows after connecting +- **Auto-reconnect** — automatically reconnect with exponential backoff when the connection drops unexpectedly - **Host key verification** — four policies: strict, ask, accept-new, and insecure - **Session recording** — capture terminal output to asciicast v2 files for later playback - **OpenSSH config import** — reads your existing `~/.ssh/config` to create connection profiles @@ -103,6 +123,8 @@ Full-featured SSH client with support for: - Option negotiation, configurable character encoding (UTF-8 and others) - Local echo and line mode settings - Configurable line endings +- Auto-login scripts (expect-style send/wait sequences) +- Auto-reconnect with exponential backoff ### RAW TCP @@ -119,6 +141,56 @@ Full-featured SSH client with support for: --- +## Power Features + +### Broadcast Input + +Press **Cmd+Shift+B** (or click the broadcast button in the tab bar) to toggle broadcast mode. When active, everything you type is sent to **all connected sessions** simultaneously — ideal for running the same command across multiple servers. The broadcast button pulses red to remind you it's active. + +### Snippet Library + +Press **Cmd+Shift+S** to open the snippet library. Save frequently-used commands (e.g. `sudo systemctl restart nginx`) with a name, description, and optional folder/tags. You can send a snippet to the active session with one click, or access snippets from the right-click context menu. + +### Terminal Search + +Press **Cmd+F** to open the search overlay on the active terminal. Features include: + +- Case-sensitive toggle (**Aa** button) +- Regular expression toggle (**.*** button) +- Match count indicator +- Navigate through matches with up/down arrows or Enter/Shift+Enter + +### Right-Click Context Menu + +Right-click anywhere in the terminal to access: + +- **Copy** — copy selected text to clipboard +- **Paste** — paste from clipboard +- **Select All** — select all terminal content +- **Find** — open the search overlay +- **Send Snippet** — quickly send a saved command +- **Clear** / **Reset** — clear the terminal buffer + +### Auto-Login Scripts + +For SSH and Telnet connections, you can define expect-style login scripts in the profile editor. Each script is a sequence of **wait** (match text from the server) and **send** (send text + newline) steps that run automatically after connection. Useful for: + +- Automating password prompts on bastion hosts +- Navigating menu-driven systems +- Running initial setup commands + +Each wait step has a configurable timeout (default 10 seconds). + +### Auto-Reconnect + +Enable auto-reconnect in the profile's Advanced section. When an SSH or Telnet connection drops unexpectedly, Nexus Terminal will automatically attempt to reconnect using exponential backoff (1s, 2s, 4s, 8s… up to 30s between attempts). You can configure the maximum number of attempts (default 5). + +### Quick Connect + +Press **Cmd+Shift+Q** to open a lightweight connect dialog. Choose SSH, Telnet, or RAW; enter the host and port; and connect immediately without creating a saved profile. + +--- + ## Security Nexus Terminal takes credential storage seriously. Your passwords and private key passphrases are never stored in plain text. @@ -139,6 +211,10 @@ Nexus Terminal takes credential storage seriously. Your passwords and private ke | Salt | 32 random bytes (unique per vault) | | Nonce | Random, prepended to ciphertext | +### TOTP/2FA + +For SSH servers that use two-factor authentication, you can store a TOTP secret in the profile's encrypted vault. During keyboard-interactive authentication, Nexus Terminal detects 2FA prompts (verification code, OTP, authenticator, etc.) and automatically generates and submits a 6-digit time-based code. You can test the secret from the profile editor before connecting. + ### Known Hosts When you connect to an SSH server for the first time, Nexus Terminal can remember the server's fingerprint. You choose one of four policies per profile: @@ -168,7 +244,7 @@ internal/ storage/ — SQLite repository (WAL mode) with embedded sequential migrations secrets/ — two-tier credential storage (OS keychain + encrypted file vault) models/ — shared domain types, protocol configs, and defaults - sshclient/ — SSH client with agent support + sshclient/ — SSH client with agent, proxy, and TOTP support telnetclient/ — Telnet with option negotiation rawclient/ — RAW TCP with hex encoding githubclient/ — GitHub API integration @@ -182,7 +258,7 @@ internal/ audit/ — timestamped audit logging frontend/ - src/js/ — 15 IIFE-wrapped JS modules (no framework, no bundler) + src/js/ — 18 IIFE-wrapped JS modules (no framework, no bundler) src/css/ — modular stylesheets with design tokens (tokens.css) ``` @@ -237,6 +313,18 @@ If you're using the encrypted file vault (rather than the OS keychain), you'll n **SSH connection fails with "host key verification failed"** Your profile's host key policy may be set to **strict** and the server's key has changed (or hasn't been saved yet). Open the profile settings and choose **ask** if you'd like to be prompted, or verify the server's key and update your known hosts. +**SSH connection fails through a proxy** +Check that your proxy host, port, and type (SOCKS5 or HTTP CONNECT) are correct in the profile's Proxy section. If the proxy requires authentication, make sure the username and password are filled in. SOCKS5 defaults to port 1080; HTTP CONNECT defaults to port 8080. + +**TOTP/2FA code is rejected** +Ensure the TOTP secret is correct (base32-encoded) and that your system clock is accurate. Time-based codes are only valid for 30-second windows. Use the "Test" button in the TOTP section of the profile editor to verify the secret generates valid codes. + +**Auto-reconnect keeps failing** +The connection must have been successfully established at least once. Auto-reconnect uses the same credentials as the original connection. If the server is genuinely unreachable, reconnection attempts will exhaust after the configured maximum (default 5 attempts). + +**Login script times out** +Each "wait" step has a configurable timeout (default 10 seconds). If the server takes longer to produce the expected text, increase the timeout in the profile editor. Check that the wait pattern matches exactly — it's a plain text substring match, not a regex. + **Terminal text looks wrong or garbled** Check the character encoding setting on the connection profile. Most modern servers use UTF-8, but some older systems may need a different encoding. diff --git a/frontend/src/js/settings.js b/frontend/src/js/settings.js index ca6dcf6..599af14 100644 --- a/frontend/src/js/settings.js +++ b/frontend/src/js/settings.js @@ -372,6 +372,8 @@ class Settings {
Need to connect quickly without saving a profile? Press ⌘⇧Q / Ctrl+Shift+Q to open the quick connect dialog. Choose SSH, Telnet, or RAW, enter the host and port, and you're connected immediately.
Right-click any connection in the sidebar to edit, duplicate, or delete it. You can drag connections between groups, and use the search box to filter by name, host, or tag.
` }, @@ -383,14 +385,29 @@ class Settings {ssh-agent or 1Password).If your server requires a time-based one-time password (TOTP) during login, you can store the TOTP secret in the profile editor under the TOTP / 2FA section. When connecting, Nexus Terminal will detect 2FA prompts (such as "Verification code" or "OTP") and automatically generate and submit a 6-digit code. Use the Test button to verify your secret generates valid codes before connecting.
If you need to reach a server through an intermediate host, add one or more jump hosts in the connection editor. Nexus Terminal will tunnel through each hop automatically.
You can set up local, remote, and dynamic (SOCKS proxy) port forwards in the connection editor. These start automatically when the session connects.
+If you need to connect through a proxy, open the Proxy section in the profile editor. Nexus Terminal supports SOCKS5 and HTTP CONNECT proxies, with optional username/password authentication. The proxy is used to reach the SSH server (or the first jump host if jump hosts are configured).
Once connected to an SSH server, click the 📁 icon on the tab to open the SFTP file browser. You can browse directories, upload, download, rename, and delete files from a side panel.
Tick "Agent Forwarding" in the SSH settings to forward your local SSH agent to the remote server. This lets you use your local keys when connecting onward from that server.
+Define expect-style login scripts to automate interactions after connecting. In the Login Script section of the profile editor, add a sequence of Wait for (match text from the server) and Send (send text + newline) steps. For example:
+login:adminPassword:mysecretpasswordEach wait step has a configurable timeout (default 10 seconds). Steps execute in order after the connection is established.
+Enable Auto-Reconnect in the Advanced section to automatically reconnect when the connection drops unexpectedly. Reconnection uses exponential backoff (1s, 2s, 4s, 8s... up to 30s). You can configure the maximum number of attempts (default 5).
` }, { id: 'telnet', title: 'Telnet Connections', content: `Telnet is an older, unencrypted protocol still used for network equipment, legacy systems, and some fun internet services.
@@ -399,6 +416,8 @@ class Settings {Note: Telnet sends everything in plain text. Avoid using it for anything sensitive over an untrusted network.
` }, @@ -439,8 +458,38 @@ class Settings {Drag the divider between panes to resize them.
+Press ⌘⇧B / Ctrl+Shift+B to toggle broadcast mode. When active, everything you type is sent to all connected sessions simultaneously — perfect for running the same command across multiple servers. The broadcast button in the tab bar pulses red to remind you it's active.
Press ⌘⇧R / Ctrl+Shift+R to start recording a session. A red dot will appear on the tab. Press the same shortcut again to stop. Browse and replay recordings from the ⏺ button in the sidebar.
+Right-click in the terminal to access a context menu with:
+Press ⌘⇧S / Ctrl+Shift+S to open the snippet library. Save frequently-used commands with a name, description, and optional folder and tags. Click Send to Session to inject a command into the active terminal. You can also access snippets from the right-click context menu.
+Press ⌘F / Ctrl+F to open the search overlay on the active terminal. Features include:
+Press ⌘⇧Q / Ctrl+Shift+Q to open a lightweight connect dialog. Choose SSH, Telnet, or RAW; enter the host and port; and connect immediately without creating a saved profile.
+For SSH and Telnet connections, you can define expect-style login scripts — a sequence of "wait for text" and "send text" steps that execute automatically after connecting. Configure them in the Login Script section of the profile editor.
+Enable auto-reconnect in a profile's settings to automatically reconnect when a connection drops. Uses exponential backoff with a configurable maximum number of attempts.
` }, { id: 'security', title: 'Security & Credentials', content: `The vault uses Argon2id to derive the encryption key from your master password (128 MiB memory, making brute-force attacks very expensive). Each secret is individually encrypted and never stored in plain text.
+TOTP secrets for SSH two-factor authentication are stored alongside your other credentials — encrypted in the OS keychain or the file vault. They are never saved in the profile database in plain text.
When you connect to an SSH server for the first time, Nexus Terminal records the server's fingerprint. If the fingerprint changes on a subsequent connection, you'll be warned — this protects against man-in-the-middle attacks.
You can manage known hosts and change the verification policy in Settings → Known Hosts.
@@ -469,9 +520,12 @@ class Settings {600 or 400).Connect via SSH to ssh.github.com on port 443 (or github.com on port 22) with your GitHub username. GitHub will greet you by name if your key is set up correctly — a quick way to verify your SSH configuration.
Create a RAW TCP connection to any HTTP server on port 80, then type GET / HTTP/1.0 followed by two blank lines. You'll see the raw HTTP response — a great way to understand how the web works under the hood.
Open two or more sessions (e.g. to different servers) and press ⌘⇧B / Ctrl+Shift+B to turn on broadcast mode. Everything you type goes to all sessions at once — try running hostname and watch them all respond with different names!