<?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: Nicholas Santi</title>
    <description>The latest articles on DEV Community by Nicholas Santi (@nicksan222).</description>
    <link>https://dev.to/nicksan222</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4184814%2F7f7171b8-6c98-429a-98a7-dbac97658528.png</url>
      <title>DEV Community: Nicholas Santi</title>
      <link>https://dev.to/nicksan222</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nicksan222"/>
    <language>en</language>
    <item>
      <title>Easy SSH for AI desktop tooling</title>
      <dc:creator>Nicholas Santi</dc:creator>
      <pubDate>Wed, 14 Oct 2026 14:06:51 +0000</pubDate>
      <link>https://dev.to/nicksan222/easy-ssh-for-ai-desktop-tooling-461</link>
      <guid>https://dev.to/nicksan222/easy-ssh-for-ai-desktop-tooling-461</guid>
      <description>&lt;p&gt;A project can feel like its own development machine without staying running all day. Give its devcontainer an SSH alias, and let connections control its lifecycle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Connect to projects-example
    → start the devcontainer if needed
    → open an SSH session inside it

Close the last connection
    → wait a short grace period
    → stop the project's containers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An SSH-capable editor such as T3 Code gets a remote environment. A terminal gets a shell where you can run a coding agent such as Codex CLI. The project keeps its existing development-container setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with the devcontainer CLI
&lt;/h2&gt;

&lt;p&gt;With Docker running and the CLI installed, start an existing checkout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @devcontainers/cli

devcontainer up &lt;span class="nt"&gt;--workspace-folder&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/Projects/example"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CLI uses the project's definition and applicable lifecycle hooks. Its output identifies the container's user and workspace. It does not automatically clone the repository: the workspace follows the definition, often mounting your existing checkout. &lt;a href="https://code.visualstudio.com/docs/devcontainers/devcontainer-cli" rel="noopener noreferrer"&gt;CLI documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The container also needs an SSH server and your public key in the login user's &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt;. For Debian/Ubuntu containers, the official &lt;a href="https://github.com/devcontainers/features/tree/main/src/sshd" rel="noopener noreferrer"&gt;SSH server feature&lt;/a&gt; supplies the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"features"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ghcr.io/devcontainers/features/sshd:1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Merge this into your definition and rebuild if needed. Add the public key separately; installing an SSH server does not configure authentication for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let the SSH alias start the environment
&lt;/h2&gt;

&lt;p&gt;An ordinary SSH alias can run a connection helper using &lt;code&gt;ProxyCommand&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Host projects-example
  HostName localhost
  User vscode
  ProxyCommand ~/bin/project-ssh example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the actual container user. &lt;code&gt;project-ssh&lt;/code&gt; is a small lifecycle script you supply, rather than a built-in command. Its job is to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Resolve the project's checkout.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;devcontainer up&lt;/code&gt; when the environment is stopped.&lt;/li&gt;
&lt;li&gt;Connect SSH to the container's server.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The transport can use Docker directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;--user&lt;/span&gt; root &lt;span class="nt"&gt;-i&lt;/span&gt; CONTAINER_ID /usr/sbin/sshd &lt;span class="nt"&gt;-i&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The container ID comes from startup. Docker carries the SSH stream; the server handles login as the configured user. This avoids assigning a listening port to each project. Keep setup messages on stderr so stdout remains the SSH protocol stream. &lt;a href="https://man.openbsd.org/sshd" rel="noopener noreferrer"&gt;OpenSSH server documentation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Stop after the last connection—not the first
&lt;/h2&gt;

&lt;p&gt;The helper also tracks live connections. Simultaneous connections share one startup operation and reuse the same container.&lt;/p&gt;

&lt;p&gt;When the last connection closes, start a timer—for example, 60 seconds. A new connection cancels that timer. If the project stays idle, stop its containers and retain their files and volumes. For a Compose project, include its dependency containers too.&lt;/p&gt;

&lt;p&gt;This requires a little lifecycle bookkeeping outside SSH. &lt;code&gt;ProxyCommand&lt;/code&gt; supplies the connection hook; SSH configuration has no built-in “stop my devcontainer when idle” setting. A small script and an idle watcher are sufficient; no Python-specific design is required. &lt;a href="https://man.openbsd.org/ssh_config" rel="noopener noreferrer"&gt;SSH configuration reference&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An editor may keep its SSH connection open between chats. Closing a chat therefore might not stop the environment. Disconnecting the environment releases that connection. Background jobs stop too when the container shuts down.&lt;/p&gt;

&lt;h2&gt;
  
  
  macOS, Linux and WSL
&lt;/h2&gt;

&lt;p&gt;The flow is the same. The Docker host and the location of the SSH client differ:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Where to run it&lt;/th&gt;
&lt;th&gt;What changes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;macOS&lt;/td&gt;
&lt;td&gt;Your Mac terminal, with Docker Desktop or Colima running&lt;/td&gt;
&lt;td&gt;Docker runs Linux containers in a VM. The alias and helper live on the Mac.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linux&lt;/td&gt;
&lt;td&gt;Your Linux terminal, with Docker Engine available&lt;/td&gt;
&lt;td&gt;No Docker VM is needed. The alias and helper live on the Linux host.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows with WSL 2&lt;/td&gt;
&lt;td&gt;Your WSL terminal, with Docker Desktop integration enabled&lt;/td&gt;
&lt;td&gt;Install the CLI and helper inside WSL; keep the checkout in its Linux filesystem.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For WSL, enable Docker Desktop integration for the distribution you use. A Windows application using Windows SSH does not automatically read WSL's &lt;code&gt;~/.ssh/config&lt;/code&gt;: it needs a supported way to connect through WSL, or a separate Windows-side setup. &lt;a href="https://docs.docker.com/desktop/features/wsl/" rel="noopener noreferrer"&gt;Docker's WSL guide&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Use it from your coding tool
&lt;/h2&gt;

&lt;p&gt;First check the alias in a terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh projects-example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then select that SSH environment in your editor and point it at the container workspace reported by the CLI. Install any coding CLI you want to run inside the container as part of its setup.&lt;/p&gt;

&lt;p&gt;The daily interaction becomes simple: select the project, work in its environment, then disconnect. The devcontainer definition controls the project; the connection helper controls when it runs.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>beginners</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
