github fpenezic/ssh-tool v1.2.0

one hour ago

The Database grid works more like a spreadsheet: edit cells in place, select and copy blocks of cells straight into Excel or Teams, right-click menus on cells and in the tree, and export a whole table to CSV or JSON. The app proxy routes names by the VPNs' DNS domains, the Kafka consumer can show the newest records of a whole topic, the UI font size now means the text size, and the user guide has step-by-step How-to recipes.

Appearance

  • UI font size means the text size: the number in Settings > Appearance is now the size of the main text, and field labels, badges and titles are one step smaller or larger than it instead of a dozen fractions of it, with nothing under 10px. At 11, labels and notes that were 8 to 9px are now 10px. Text fields, selects and buttons in Settings share one height that grows with the font.
  • On / off options in Settings are switches, like the App proxy one; option cards put the radio or switch beside the title instead of on a line of its own; a section heading inside a card no longer renders larger than the card's own title.
  • Disable WebGL renderer in Settings > Terminal is now GPU rendering (WebGL) and reads the positive way round: off (the default, as before) draws with canvas, on draws new tabs on the graphics card. The stored setting is unchanged, so nothing flips on upgrade. On Android terminal tabs always use canvas.

Connection tree

  • The tree filter's placeholder says it matches tags too, as it always has.
  • Quick palette (Ctrl+K): with hosts marked (Ctrl+Enter), Enter on a host that is not marked opens it together with the marked ones; it used to open only the marked ones, so the last host picked was left out. The footer says "+ this" when it will be added.
  • Filtering a large tree is several times faster: with 1000 connections the first letter typed takes about a third of the time it did and narrowing to a few folders about a tenth; typing a word applies the filter once after a short pause instead of after every letter. The tree looks up folders and connections by id instead of scanning the whole list for every row.

Network profiles

  • The app proxy routes by DNS domain: a name in a VPN's domain goes through that VPN as a name and is resolved by its DNS, so db1.prod.example.com works through the proxy even when this machine cannot resolve it. The domains come from the server (search domains from OpenConnect, OpenVPN and Check Point, split DNS from OpenConnect) and from Extra DNS domains on the profile's Proxy tab; the longest one wins. A short name this machine cannot resolve (db1) is tried in the VPN's search domains. Which VPN for... names the domain.
  • NetBird and Tailscale profiles remember what their plugin reports about the tunnel, like OpenConnect and OpenVPN: with NetBird plugin 1.7 or later (on NetBird 0.82) that is the NetBird DNS domain and the nameserver groups' domains, so names in them route through the app proxy with nothing added by hand.
  • The NetBird setup key field takes the whole netbird up --management-url ... --setup-key ... command the dashboard shows when adding a peer and keeps just the key (filling an empty Management URL); a personal access token (nbp_...) is refused at once instead of failing as "setup key is invalid" after a minute.
  • The app proxy's summary counts each VPN's DNS domains next to its networks, so a VPN reached by domain only (NetBird without network routes) is listed too.
  • A connection on an auto-mode profile whose plugin is not installed says so: the host was reachable directly, so the connect went ahead without the VPN and gave no hint the profile could never bring its tunnel up. A warning now shows once per profile while the app runs; click it to open the profile and install the plugin.
  • Changing a profile's local proxy to a port that is already taken keeps the proxy listening on its old port; before, it stopped listening until the app restarted, while the profile still showed it on.
  • A DNS domain added by hand beats one a VPN server pushed on another profile, whatever their lengths: with example.com added on B and vpn.example.com pushed by A's gateway, db1.vpn.example.com now goes to B until vpn.example.com is added by hand on A. A server can push any domain, even another customer's. Domains of different profiles that claim the same names are listed under the app proxy's summary as overlaps, and Which VPN for... says when a hand-added domain won.
  • The NetBird setup key hint says a reusable key is always needed (every tunnel start registers the machine again), not only for a synced profile.
  • A WireGuard config whose DNS line also names search domains, as wg-quick allows (DNS = 10.0.0.53, corp.example.com), was refused as a bad DNS address. The names are now search domains: a short name like db1 is tried in them inside the tunnel (the next one only when the name does not exist), and the app proxy routes names in them through the profile as if they were added by hand. A mistyped resolver address is still refused rather than taken for a domain.

Database

  • A folder's list of databases shows and can be edited with the folder's own Database switch off, so it can list prod / stage for the connections under it that turn the Database on, without turning it on for all of them.
  • Edit cells in place in a table's Data view (SQL engines, not on a read-only connection): double-click, F2 or Enter types into the cell itself; Enter keeps the value and moves down, Tab moves right, Esc drops it. Long and multi-line values still open in the pane below, and Shift+Enter opens it for any cell.
  • Changed cells stay visible: a yellow mark in the cell's corner, the row number in yellow and the old value on hover, also while the cell is picked (its blue used to hide the yellow).
  • Select and copy blocks of cells: Shift+click, Shift+arrows, a drag, a click on # for rows, Ctrl+A. Ctrl+C copies them as a table that Excel splits into cells and Teams / Outlook paste as a table.
  • Right-click on a cell: Edit, Set NULL, Revert the change, Open value, Copy value (or the selected block), Copy with headers, Copy as Markdown, Copy as WHERE, and in a table's Data view Copy as INSERT / DELETE of the selected rows (Copy as SQL above the grid takes the selection too; INSERT carries the changed values, DELETE matches the rows as they are on the server).
  • Right-click in the tree: open a table's Data, Structure or DDL, New query, Count rows, Copy name, Copy DDL, Export to CSV / JSON, ER diagram; New query, Copy name and Refresh tables on a database.
  • Export a whole table to CSV or JSON (SQL engines and ClickHouse), read 10000 rows at a time with a progress bar and Stop, not only the page shown.
  • Script no longer asks to drop the edits it has just put into the query tab.
  • Adding a database to a connection's list no longer turns the Query timeout field red: an empty new entry is its own error (Save says it needs a name), not the timeout's.
  • Read-only connections refuse more: an OpenSearch / Elasticsearch POST whose path a proxy in front of the server could rewrite into another endpoint (. or .. segments, ;, //, encoded slashes: /logs/_search/../_delete_by_query is a delete there); PostgreSQL EXPLAIN (ANALYSE) ..., the British spelling, and EXPLAIN ("analyze") ... with the option quoted, both of which run the statement (they also count as writes for the sensitive-connection confirm); on SQL Server SETUSER, RAISERROR, WAITFOR and CHECKPOINT; on Oracle and Db2 seq."NEXTVAL" written as a quoted name; on Redis and Valkey CONFIG GET patterns that can match a password setting (CONFIG GET *, any [...] pattern), ACL LIST and ACL GETUSER, whose replies carry passwords or their hashes.
  • JSON export of a result with two columns of one name keeps both values: the repeat is named name (2) (it used to keep only the last one).

Kafka

  • Stop at end no longer hangs on a busy transactional topic: a partition whose end offset is a transaction commit marker never delivers that offset, and the 5 second idle rule that ends the read was reset by records arriving in other partitions, so the consumer could keep running. Only records still below an end count now.
  • Last N in topic: a consumer start point that shows the newest N records of the topic as a whole, by record time, oldest first, instead of the last N of every partition. It reads the last N offsets of each partition, keeps the newest N records and shows them once every partition is read (or after 5 seconds with nothing more from the ones still being read: a very slow partition misses the pick, and what it sends later follows the pick as if new); without stop at end it then follows new records. A record limit keeps the newest of the pick and ends the read when reached; the pick also stays within the consumer's buffer (records and bytes), so very large records can make it shorter than N. Compacted or transactional partitions hold fewer records than offsets in that window, so the pick can be shorter than N. The MCP kafka_consume tool takes it as from=newest; a consumer group cannot be reset to it.

Audit log

  • Audit events a restored older backup brought back into the main store moved to the audit log only when the audit log was empty; otherwise they stayed in the main store, out of the audit view and its purge, and travelled with backups and sync. They move on the next start now, without duplicating events already there.

Documentation

  • How-to recipes in the user guide and on the wiki: a host behind a VPN and a jump host with opkssh, Kafka or a database read-only for production, a GitLab CI job into customer networks, moving from RDM / MobaXterm / PuTTY, secrets and one-time codes from KeePass / Bitwarden / Infisical, one profile on two computers with backups, and sharing a session with a colleague or an AI assistant.
  • The Settings chapter follows the app's Settings groups and covers every section; stale "not in the app yet" items and Settings paths are fixed.

Don't miss a new ssh-tool release

NewReleases is sending notifications on new releases.