<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: doctorqp</title>
    <description>The latest articles on DEV Community by doctorqp (@doctorqp).</description>
    <link>https://dev.to/doctorqp</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F895433%2F2767db1a-b7c3-46f1-bce3-9e23b6e55738.png</url>
      <title>DEV Community: doctorqp</title>
      <link>https://dev.to/doctorqp</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/doctorqp"/>
    <language>en</language>
    <item>
      <title>I built a terminal SSH manager because I was tired of scrolling bash history</title>
      <dc:creator>doctorqp</dc:creator>
      <pubDate>Mon, 08 Jun 2026 14:14:49 +0000</pubDate>
      <link>https://dev.to/doctorqp/i-built-a-terminal-ssh-manager-because-i-was-tired-of-scrolling-bash-history-1a0d</link>
      <guid>https://dev.to/doctorqp/i-built-a-terminal-ssh-manager-because-i-was-tired-of-scrolling-bash-history-1a0d</guid>
      <description>&lt;p&gt;I manage a handful of servers across client environments. Some use key auth, some use passwords, and most of the time I need root access once I'm in. The workflow was always the same: scroll through terminal history for the right &lt;code&gt;ssh&lt;/code&gt; command, type the password, then &lt;code&gt;sudo -i&lt;/code&gt; and type it again.&lt;/p&gt;

&lt;p&gt;I built SSHM to skip all of that. It's a terminal app that stores server credentials, keeps passwords in macOS Keychain, and optionally elevates to root automatically after login. One keypress to connect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pipx &lt;span class="nb"&gt;install &lt;/span&gt;sshm-terminal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you don't have pipx:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;pipx &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pipx ensurepath
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or via Homebrew directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew tap dailydeploy365/tap &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; brew &lt;span class="nb"&gt;install &lt;/span&gt;sshm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Add a server
&lt;/h2&gt;

&lt;p&gt;Launch with &lt;code&gt;sshm&lt;/code&gt;, press &lt;code&gt;a&lt;/code&gt; to open the add form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Name:       Production API
Host / IP:  192.168.1.50
Port:       2222
User:       deploy
Group:      production
Password:   ••••••••
SSH Key Path: (leave empty if using password)

☑ Auto sudo (elevate to root)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Press &lt;code&gt;ctrl+s&lt;/code&gt; to save. The password goes straight into macOS Keychain. Server metadata is stored in &lt;code&gt;~/.sshm/servers.json&lt;/code&gt; with no secrets in it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect
&lt;/h2&gt;

&lt;p&gt;Select the server with arrow keys and press &lt;code&gt;Enter&lt;/code&gt;. That's it.&lt;/p&gt;

&lt;p&gt;If you checked "Auto sudo," the app SSHs in, waits for the shell prompt, runs &lt;code&gt;sudo -i&lt;/code&gt;, handles the password prompt, and drops you into a root shell. You don't type the password at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the password security works
&lt;/h2&gt;

&lt;p&gt;Passwords never touch disk as plaintext. The macOS &lt;code&gt;security&lt;/code&gt; CLI writes them to Keychain with a service tag of &lt;code&gt;sshm&lt;/code&gt;. You can verify in Keychain Access.app by searching for "sshm."&lt;/p&gt;

&lt;p&gt;During connection: when sshpass is available, the password is passed through an environment variable (&lt;code&gt;SSHPASS&lt;/code&gt;), which never hits a file. When falling back to &lt;code&gt;expect&lt;/code&gt;, a temp file with &lt;code&gt;0400&lt;/code&gt; permissions is created, the expect script reads it, deletes it immediately, then handles the SSH prompt. Cleanup happens in a &lt;code&gt;finally&lt;/code&gt; block.&lt;/p&gt;

&lt;h2&gt;
  
  
  Auto-sudo in detail
&lt;/h2&gt;

&lt;p&gt;The auto-sudo feature chains two expect sequences:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;SSH into the server and send the password at the login prompt&lt;/li&gt;
&lt;li&gt;Wait for the shell prompt (looks for &lt;code&gt;user@host:...$&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Send &lt;code&gt;sudo -i&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Send the same password at the sudo prompt&lt;/li&gt;
&lt;li&gt;Hand control to you with &lt;code&gt;interact&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This assumes the SSH user has sudo privileges and that the sudo password matches the SSH password. That's the common setup for most cloud VMs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keyboard shortcuts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;a&lt;/code&gt; Add a new server&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;e&lt;/code&gt; Edit selected server&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;d&lt;/code&gt; Delete selected server&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Enter&lt;/code&gt; SSH into selected server&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;c&lt;/code&gt; Copy SSH command to clipboard&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/&lt;/code&gt; Search and filter servers&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;q&lt;/code&gt; Quit&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  SSH keys
&lt;/h2&gt;

&lt;p&gt;Leave the Password field empty and fill in the SSH Key Path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SSH Key Path:  ~/.ssh/id_rsa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The app uses &lt;code&gt;ssh -i&lt;/code&gt; when connecting. No expect scripts, no sshpass.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;macOS (uses the &lt;code&gt;security&lt;/code&gt; CLI for Keychain and &lt;code&gt;expect&lt;/code&gt; for password automation)&lt;/li&gt;
&lt;li&gt;Python 3.10+&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is macOS-only because of the Keychain dependency. Linux support (via &lt;code&gt;secret-tool&lt;/code&gt; or &lt;code&gt;pass&lt;/code&gt;) isn't built yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/dailydeploy365/sshm" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Install: &lt;code&gt;pipx install sshm-terminal&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dailydeploy.in/blog/sshm-terminal-ssh-manager/" rel="noopener noreferrer"&gt;Full writeup on dailydeploy.in&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you manage multiple servers and want a cleaner workflow, give it a try. Feedback and PRs welcome.&lt;/p&gt;

</description>
      <category>ssh</category>
      <category>python</category>
      <category>macos</category>
      <category>cli</category>
    </item>
  </channel>
</rss>
