SSH & Remote Agent

Nexion turns remote servers into first-class workspaces. Connect via SSH, browse remote files, edit code, run Git operations, and manage tmux sessions: all through the same native macOS interface you use locally. A lightweight remote agent is automatically deployed to each server to power the Finder, Git panel, and file operations over a secure JSON-RPC channel.

SSH Connections

Quick Connect

Open the SSH Quick Connect panel with Cmd+S from the Open Project dialog, or via the menu. Enter a host (or select from your SSH config) to connect instantly.

SSH Bookmarks

Save frequently used connections as bookmarks with custom names, colors, remote working directories, and identity files. Bookmarks appear in the Open Project dialog and are used for session restore.

Authentication

Nexion supports all standard SSH authentication methods:

  • • SSH keys: Public key authentication via ~/.ssh/config with IdentityFile.
  • • 1Password SSH Agent: Nexion allocates a real PTY for SSH authentication. That lets 1Password's biometric/PIN prompts run interactively, which most GUI SSH clients block.
  • • macOS Keychain: Passphrase-protected keys can have their passphrase stored in Keychain. Nexion can pre-authenticate in the background without prompting.
  • • Jump hosts: ProxyJump / ProxyCommand configurations are respected from your SSH config.

Connection Multiplexing

Each SSH tab creates its own ControlMaster socket with ControlPersist=10m. This enables:

  • • Instant sub-connections: The remote agent, Git operations, and tmux commands all multiplex through the same SSH connection. No additional authentication needed.
  • • Independent tabs: Each tab has its own socket, so closing one tab doesn't affect others connected to the same host.
  • • Graceful persistence: Sockets stay alive for 10 minutes after the last session disconnects, so reconnecting is instant.

When the Connection Drops

A remote tab is expected to outlive the network under it. Losing the connection is treated as a pause, not as the end of the session.

  • • Immediate retries: three attempts, at 0, 5 and 15 seconds. Each one rebuilds the shell in the pane, which is what creates the ControlMaster the rest of the workspace multiplexes through.
  • • Then it waits: when the retries run out Nexion keeps an eye on the host and reconnects on its own when it answers again: after a network change, after the Mac wakes, or within a minute otherwise. It waits for the host to actually come back, so a machine that is up while something else is broken is not retried in a loop.
  • • Shell and workspace both return: the terminal reconnects and the remote agent re-attaches to its daemon, so the file tree, Git and search come back with it. The Reconnect button in the status bar does the same thing on demand.
  • • The reason is on screen: host unreachable, name not resolved, connection refused, credentials rejected, host key changed. For a host on the local network the message also points at the macOS Local Network permission, which is easy to miss.
  • • The file tree says it is stale: while the connection is being rebuilt the remote tree stays readable but dims and shows “last known files”, rather than passing an old listing off as the state of the machine.

Remote Agent

The remote agent is a small Go binary (~3 MB) that Nexion automatically installs on each server you connect to. It runs as a background daemon and powers all remote workspace features.

Architecture

The remote agent uses a three-layer architecture:

Layer Description
Daemon Background process on the remote server. Listens on a Unix socket, manages workspaces, file snapshots, Git state. One daemon per project, auto-exits after 10 minutes of inactivity.
Proxy Bridges SSH stdin/stdout to the daemon's Unix socket. Launched per-connection, starts the daemon if not running.
Client The Nexion macOS app. Sends JSON-RPC 2.0 requests through the SSH tunnel to the proxy/daemon.

Bootstrap Process

When you open an SSH tab, Nexion runs a three-phase bootstrap:

  1. Detect: Runs uname -sm to determine the remote OS and architecture (Linux x86_64, Linux arm64, Darwin arm64).
  2. Install: Checks if the agent is installed and up to date. If missing or older, uploads the correct binary via SCP (atomic install with temp file + rename). If the remote agent is newer than the bundled version, it is kept as-is. Nexion never downgrades.
  3. Start: Launches the proxy, which connects to the daemon (starting it if needed). Performs a hello handshake to negotiate capabilities.

Capabilities

The hello handshake reports what the remote environment supports:

Capability Description
search_backend rg (ripgrep) if installed, otherwise grep
write_file Atomic file writes with optimistic locking (mtime check)
git_snapshot Remote Git status, branches, commit, push
reconnect Fast reconnect to existing daemon without full bootstrap

What the Agent Enables

  • • Remote Finder: Browse files and directories on the remote server with the same Finder panel used locally. The agent maintains a file tree snapshot and pushes incremental updates.
  • • Remote Editor: Open and edit remote files directly. Changes are written atomically on the server with mtime-based conflict detection.
  • • Remote Git: Full Git panel support: view status, stage/unstage files, commit, push, switch branches, all executed on the remote server.
  • • Remote Search: Content search across remote files using ripgrep (when available) or grep. Results stream back in real time.
  • • tmux Control Plane: List, create, kill, and configure tmux sessions on the remote host via RPC, no subprocess SSH needed when the agent is connected.

Version Compatibility

Nexion is designed for environments where multiple team members connect to the same server with different app versions:

  • • No downgrade: If a colleague installed a newer agent on the server, your older Nexion will use it as-is. The newer agent is backward-compatible with older clients.
  • • Update suggestion: When the remote agent is newer than your app, Nexion shows a non-blocking notification suggesting you update to get the latest features.
  • • Atomic install: Binary uploads use a temp file + atomic rename, so a partial upload never corrupts the installed agent.
  • • Daemon locking: An exclusive file lock prevents two daemons from running for the same project, even when multiple clients connect simultaneously.

Remote File Paths

The agent installs to ~/.nexion/ on the remote server:

Path Purpose
~/.nexion/bin/nexion-remote-agent Agent binary (auto-installed, auto-updated)
~/.nexion/bin/nexion-shell-bootstrap-v* Shell bootstrap script (versioned per client)
~/.nexion/run/agent-*.sock Daemon Unix socket (one per project)
~/.nexion/run/agent-*.pid Daemon PID file
~/.nexion/run/agent-*.log Daemon log output

Session Restore

SSH tabs are fully persisted across app restarts. When you reopen Nexion:

  • • SSH connections are re-established automatically (with 1Password/Keychain support).
  • • The remote agent reconnects to the existing daemon (if still running) or bootstraps a new one.
  • • tmux sessions are re-attached if the tab was a tmux attach tab.
  • • Bookmark settings (name, color, remote directory) are restored from the saved state.

Security

  • • No open ports: The agent communicates exclusively over Unix sockets (chmod 0600). No TCP listeners, no network exposure.
  • • Path containment: All file operations are confined to the workspace root. Path traversal attempts (.., symlink escapes) are rejected.
  • • No shell injection: Git and system commands are executed with exec.Command (direct exec, no shell interpolation). Arguments are never passed through sh -c.
  • • Input validation: All RPC parameters are validated (size limits on queries, path validation, argument sanitization).
  • • Auto-cleanup: The daemon exits after 10 minutes of inactivity and removes its socket, PID, and lock files.

Troubleshooting

Problem Solution
"Finder Unavailable" Click Retry. If persistent, check the remote agent log: cat ~/.nexion/run/agent-*.log
"Failed to detect remote platform" SSH connection failed. Verify ssh hostname works from the terminal. Check port, user, and key configuration.
"Hello handshake failed" The agent proxy couldn't connect to the daemon. Kill stale processes: pkill -f nexion-remote-agent and reconnect.
A connection failed and the message is not enough Every SSH command Nexion runs on its own behalf records its failures, with what ssh actually said, in ~/.nexion/ssh-diagnostics.log. It keeps its last megabyte.
The host is back but the tab still looks disconnected Nexion checks again on a network change, on wake, and once a minute, so it usually picks the session up by itself. Reconnect in the status bar does it immediately.
1Password not prompting Ensure 1Password SSH agent is enabled in 1Password settings and SSH_AUTH_SOCK points to the 1Password socket.
Slow file listing Install ripgrep on the remote server (apt install ripgrep or brew install ripgrep) for faster search.
Agent version mismatch warning Update Nexion to the latest version. The remote agent is newer (installed by a colleague with a newer app).