SSH CLI Integration
Wire SSH_AUTH_SOCK into your shell, use the agent with ssh, git, scp, rsync, and forward it across hops.
What SSH_AUTH_SOCK does
SSH clients on macOS look up the environment variable SSH_AUTH_SOCK to find an agent. If it is set, the client connects to that Unix domain socket and asks the agent for identities and signatures using the standard SSH agent wire protocol. If it is not set, the client falls back to keys on disk.
vmuxAgent serves that protocol on ~/.ssh/vmux-agent.sock. Pointing SSH_AUTH_SOCK at it is the entire integration — every standard SSH tool then routes through vmuxAgent and from there to your iPhone.
Persistent setup
You want this set in every login shell, GUI app, and SSH config that needs key access. The right place depends on your shell.
zsh (default on macOS)
Add the export line to ~/.zshrc:
echo 'export SSH_AUTH_SOCK="$HOME/.ssh/vmux-agent.sock"' >> ~/.zshrcOpen a new terminal so the new environment loads. Confirm:
echo $SSH_AUTH_SOCK
# /Users/you/.ssh/vmux-agent.sockbash
Add the same line to ~/.bash_profile:
echo 'export SSH_AUTH_SOCK="$HOME/.ssh/vmux-agent.sock"' >> ~/.bash_profileIf you also use ~/.bashrc for non-login shells, add it there too. macOS launches Terminal sessions as login shells, so ~/.bash_profile covers the common case.
fish
set -Ux SSH_AUTH_SOCK "$HOME/.ssh/vmux-agent.sock"The -U flag persists the variable across sessions; -x exports it to subprocesses.
Inheriting into GUI apps
Variables exported in ~/.zshrc are not visible to GUI apps launched from the Dock. If you want apps like Tower, GitHub Desktop, or VS Code to use vmuxAgent without launching them from a terminal, set the variable for the user agent:
launchctl setenv SSH_AUTH_SOCK "$HOME/.ssh/vmux-agent.sock"This survives until reboot. To make it permanent, add a LaunchAgents plist; that is more involved than most users need. Most people just launch the GUI from a terminal that already has the variable set.
Verifying the connection
Three commands tell you whether the agent is wired correctly.
echo $SSH_AUTH_SOCK
# /Users/you/.ssh/vmux-agent.sock
ls -l "$SSH_AUTH_SOCK"
# srw------- you staff /Users/you/.ssh/vmux-agent.sock
ssh-add -l
# 256 SHA256:abc... iphone-secure-enclave (ECDSA)The s at the start of ls -l confirms it is a socket. Mode srw------- (0600) confirms the agent set owner-only permissions. ssh-add -l confirms the agent is responding and tells you which identities the iPhone is advertising.
If ssh-add -l says The agent has no identities, see Troubleshooting — typically the iPhone is not paired or no keys exist on it yet.
Using the agent with common tools
ssh
ssh reads SSH_AUTH_SOCK automatically. Public-key authentication will try the agent's identities in order:
ssh user@example.com
# Face ID prompt on iPhone -> shell prompt on example.comIf the server's authorized_keys does not yet trust the iPhone-held key, copy the OpenSSH-formatted public key from the agent and append it on the server:
ssh-add -L
# ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyN... iphone-secure-enclavegit
git shells out to ssh for any git@ URL, so it picks up SSH_AUTH_SOCK for free:
git clone git@github.com:you/private-repo.git
git push
git pullEach operation that requires authentication produces one Face ID prompt on the iPhone. Use a session certificate (see Keys and certificates) to batch many signatures into one approval window.
scp and sftp
scp local.txt user@example.com:/tmp/
sftp user@example.comBoth tools call into ssh and inherit the agent.
rsync
rsync -a ./build/ user@example.com:/var/www/rsync uses ssh as its transport by default. Same one-prompt-per-connection model as scp.
mosh
mosh user@example.comMosh uses ssh to bootstrap the session and then switches to its own UDP protocol. The bootstrap step uses the agent; the persistent Mosh session does not require further signatures.
Agent forwarding (the -A flag)
Agent forwarding lets you SSH into host A, then SSH from host A to host B, with host A using your local agent for authentication. With vmuxAgent, the chain becomes: SSH client on host A asks vmuxAgent on your Mac, which asks RemoteSignerPhone on your iPhone, which prompts you for Face ID. Every hop is logged and approved.
Enable per host in ~/.ssh/config:
Host bastion
HostName bastion.example.com
User you
ForwardAgent yesOr per-command:
ssh -A user@bastion.example.comCaveats:
- Forwarding trusts the bastion. Anyone with root on the bastion can use your agent for as long as your session is open. Only forward to hosts you control.
- Per-hop biometric approval. Every signature triggered through the forwarded socket prompts your iPhone, the same as one initiated locally. Long sessions become tedious if every
git pushfrom the bastion needs Face ID. Use a session certificate to amortize approvals. - Compatibility. Most servers support agent forwarding; some sandboxed
sshdbuilds disable it. If the second hop fails with "Agent admitted failure to sign", the bastion likely hasAllowAgentForwarding no.
Caveats and limitations
| Caveat | What it means |
|---|---|
| Process-level access | Anything running as your user can use vmuxAgent. macOS file permissions on the socket prevent other users, but not other processes you launch. |
| Sleep behavior | When your iPhone sleeps and an APNs wake push is in flight, the first signature can take 3-6 seconds. Subsequent signatures while the phone is awake are sub-second. |
| Lockscreen pile-ups | Repeated SSH commands while the phone is asleep can fan out into multiple notifications. Tap any one; the rest will be coalesced once the phone reconnects. |
| Tunnels and ProxyJump | ssh -J bastion.example.com user@target.example.com works the same as agent forwarding. Each hop is a separate authentication and may produce one biometric prompt each. |
| Non-interactive scripts | Scripts that SSH from cron or a launchd plist will block on Face ID. Use a session certificate during the window when you want unattended signing, and revoke it on the phone afterward. |
ssh-add add/remove | ssh-add -d and ssh-add -t have no effect — vmuxAgent does not store private keys; identities are managed on the phone. |
Related
- Getting started for the first-time setup.
- Keys and certificates to amortize signature prompts.
- Security for the threat model around forwarding and process trust.
- Connecting via SSH for the remote-host side of the connection.