Remote Sessions
Overview
Section titled “Overview”Navi can aggregate Claude Code sessions from multiple remote machines via SSH into a single unified dashboard. Remote sessions have full feature parity with local sessions — you can view git info, preview output, attach, kill, rename, and dismiss them.
Quick Start
Section titled “Quick Start”- Create the configuration file at
~/.config/navi/remotes.yaml:
remotes: - name: dev-server host: dev.example.com user: sean key: ~/.ssh/id_rsa
- name: staging host: staging.example.com user: deploy key: ~/.ssh/deploy_key jump_host: bastion.example.com- Start navi — remote sessions appear automatically alongside local sessions, labeled with the remote name:
⚙️ my-local-session 2m ago ~/projects/app
⚙️ api [dev-server] 5m ago ~/work/api "Running tests..."
✅ deploy [staging] 10m ago ~/app "Deployment complete"Configuration
Section titled “Configuration”Remote machines are configured via a YAML file at ~/.config/navi/remotes.yaml. Navi reads this file on startup. If the file doesn’t exist, remote support is simply disabled — no error.
Configuration File Format
Section titled “Configuration File Format”remotes: - name: dev-server # Display name (required) host: dev.example.com # SSH hostname or IP (required) user: sean # SSH username (required) key: ~/.ssh/id_rsa # Path to SSH private key (required) sessions_dir: ~/.claude-sessions # Remote sessions directory (optional) jump_host: bastion.example.com # Jump/bastion host (optional)Fields
Section titled “Fields”| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | Yes | — | Display name shown in the TUI next to remote sessions |
host | string | Yes | — | SSH hostname or IP address |
user | string | Yes | — | SSH username |
key | string | Yes | — | Path to SSH private key file (supports ~ expansion) |
sessions_dir | string | No | ~/.claude-sessions | Path to the sessions directory on the remote machine |
jump_host | string | No | — | Jump/bastion host for reaching the target (same user and key are used) |
All four required fields (name, host, user, key) must be present or navi will report a validation error on startup.
Detailed Usage
Section titled “Detailed Usage”Attaching to Remote Sessions
Section titled “Attaching to Remote Sessions”Press Enter on a remote session. Navi runs:
ssh -i <key> -t user@host tmux attach-session -t <session>If a jump host is configured, -J user@jumphost is added. When you detach from tmux, control returns to navi.
Remote Preview
Section titled “Remote Preview”Press p to toggle the preview pane. For remote sessions, navi captures output via SSH:
tmux capture-pane -t <session> -p -S -<lines>ANSI escape sequences are stripped from the output before display. The preview works identically to local preview — same layouts, scrolling, and keybindings.
Remote Git Info
Section titled “Remote Git Info”Press G on a remote session. Navi runs a bundled git command over SSH in the session’s working directory:
cd <cwd> && \echo "BRANCH:$(git rev-parse --abbrev-ref HEAD 2>/dev/null)" && \echo "DIRTY:$(git status --porcelain 2>/dev/null | head -1)" && \echo "REMOTE:$(git remote get-url origin 2>/dev/null)" && \echo "LASTCOMMIT:$(git log -1 --format='%h %s' 2>/dev/null)" && \echo "AHEADBEHIND:$(git rev-list --left-right --count @{u}...HEAD 2>/dev/null)"The output is parsed into the same git.Info structure used for local sessions. GitHub PR detection uses the local gh CLI with the remote URL — gh does not need to be installed on the remote machine.
Remote Kill
Section titled “Remote Kill”Press x on a remote session. After confirmation, navi runs:
tmux kill-session -t <session> ; rm -f <sessions_dir>/<session>.jsonThe ; ensures the status file is cleaned up even if the tmux session was already gone.
Remote Rename
Section titled “Remote Rename”Press R on a remote session. After entering the new name, navi runs a single compound command that:
- Renames the tmux session
- Updates the
tmux_sessionfield inside the JSON status file - Renames the JSON file to match
Remote Dismiss
Section titled “Remote Dismiss”Press d on a remote session. Navi updates the remote status file to set status to "working", clear the message, and update the timestamp.
Filtering
Section titled “Filtering”Press f to cycle through session filter modes:
| Mode | Sessions Shown |
|---|---|
| All | Local and remote |
| Local | Only local sessions |
| Remote | Only remote sessions |
The current filter is shown in the footer.
How It Works
Section titled “How It Works”SSH Connection Pool
Section titled “SSH Connection Pool”On startup, navi reads ~/.config/navi/remotes.yaml and creates an SSHPool with a connection entry for each configured remote. The pool:
- Establishes SSH connections on first use (lazy connection)
- Reuses existing connections across multiple commands via Go’s
x/crypto/sshclient - Detects dead connections with keepalive probes and automatically reconnects
- Supports jump host/bastion routing by chaining SSH connections
Connection constants:
- Connect timeout: 10 seconds
- Command timeout: 30 seconds
Remote Session Polling
Section titled “Remote Session Polling”All configured remotes are polled in parallel. For each remote:
- Execute
cat <sessions_dir>/*.jsonover SSH - Parse the concatenated JSON output (handles multiple JSON objects in sequence)
- Tag each session with the remote name (
Info.Remotefield) - Merge into the main session list
If a remote is unreachable, its sessions are simply absent — the dashboard continues working with the remaining remotes.
Connection Status
Section titled “Connection Status”Each remote tracks its connection status:
| Status | Meaning |
|---|---|
connected | SSH connection active |
disconnected | Not yet connected or cleanly disconnected |
error | Connection failed (last error recorded) |
Security
Section titled “Security”- SSH key authentication only — no password storage
- Jump host support for bastion access patterns
- Shell arguments are properly quoted to prevent injection
- Host key checking is currently permissive (
InsecureIgnoreHostKey)
Troubleshooting
Section titled “Troubleshooting””Warning: failed to load remotes config”
Section titled “”Warning: failed to load remotes config””The ~/.config/navi/remotes.yaml file exists but has a syntax error or is missing required fields. Check that all remotes have name, host, user, and key fields.
Remote sessions not appearing
Section titled “Remote sessions not appearing”- Verify SSH key authentication works:
ssh -i <key> user@host "cat ~/.claude-sessions/*.json" - Check that Claude Code sessions are running on the remote and the hooks are installed there
- Verify the
sessions_dirpath is correct (must match where hooks write on the remote)
SSH connection failures
Section titled “SSH connection failures”- Connection timeout is 10 seconds — slow networks may need investigation
- If using a jump host, ensure both the jump host and target are reachable
- Check that the SSH key file exists and has correct permissions (
chmod 600)
Related Features
Section titled “Related Features”- Session Management — Session lifecycle actions (same keybindings work for remote)
- Git Integration — Git info for remote sessions uses the same display
- Preview Pane — Preview remote session output