🚀 Termalin launches on Product Hunt · September 5 — get notified →
termal.in

← Blog

What is the SSH agent, and how does ssh-add work?

· Termalin team sshssh-agentssh-keystutorial

If you’ve protected your SSH key with a passphrase — and you should have — you’ve met the annoyance the agent exists to solve: type that passphrase for every single connection, or leave the key unprotected. The SSH agent is the third option. Unlock the key once, and the agent handles every authentication after that without asking again. Here’s what it actually is, how ssh-add drives it, and the one property of it that’s worth being careful about.

The problem it solves

Your private key on disk is encrypted with your passphrase. That’s good — a stolen key file is useless without the passphrase. But it means every time ssh wants to use the key, it has to decrypt it, which means prompting you. Ten connections, ten prompts. The naive fixes are both bad: strip the passphrase (now the file is the credential — copy it and you’re the owner), or retype it constantly (so annoying that people strip the passphrase).

The agent breaks the trade-off. You decrypt the key once, into a process that holds it in memory, and every later use goes through that process. One prompt per session, and the key on disk stays encrypted.

How it works

The agent is a small background process that holds your decrypted private keys in memory — never on disk. The important part is what it does with them: it doesn’t hand the key to anyone.

When you connect, the server sends a challenge — a chunk of data it wants signed. ssh passes that to the agent; the agent signs it with the in-memory key and returns just the signature. The server verifies it against your public key and lets you in. The private key never leaves the agent — not to ssh, not over the wire, not to the server. Only signatures leave. The agent is a signing service, and the key is a secret it guards rather than a value it shares.

This is also why a passphrase prompt appears once and never again for that session: after the first ssh-add, the decrypted key lives in the agent, and every later signature is served from memory.

The commands

Start the agent. On most systems something already runs one (see the OS notes below), but to start one by hand:

eval "$(ssh-agent -s)"

ssh-agent -s prints two shell variables — SSH_AUTH_SOCK (the path to the agent’s socket) and SSH_AGENT_PID. Running it bare just prints them; the eval is what actually sets them in your current shell so ssh can find the agent. Forgetting the eval is the classic “I started the agent but nothing uses it.”

Load a key with ssh-add:

ssh-add ~/.ssh/id_ed25519       # prompts for the passphrase, once
ssh-add                          # with no path, loads the default keys

List what’s loaded:

ssh-add -l       # fingerprints of loaded keys
ssh-add -L       # the full public keys

ssh-add -l is your first diagnostic when auth fails — if the key you expect isn’t listed, the agent can’t sign with it.

Clear keys:

ssh-add -d ~/.ssh/id_ed25519    # remove one key
ssh-add -D                       # remove all keys

Add a timeout. A key that lives in the agent forever is a key that’s usable long after you walked away. -t sets a lifetime in seconds, after which the agent forgets it and you re-enter the passphrase:

ssh-add -t 3600 ~/.ssh/id_ed25519    # expires in one hour

And -c requires you to confirm — with a local prompt — every single use of the key, which pairs well with situations where the key might be reachable by more than just you.

Where the agent lives, per OS

You rarely start the agent by hand, because your OS runs one for you — but which one differs, and that’s where confusion starts.

  • Linux. Usually a systemd user service (ssh-agent.service or the gcr-ssh-agent from GNOME Keyring), started at login, with SSH_AUTH_SOCK set for your whole session. On desktops, gnome-keyring often plays the agent role and can unlock keys with your login password. If ssh-add -l says it can’t connect, your session didn’t export the socket — logging out and back in, or eval "$(ssh-agent -s)", fixes it.
  • macOS. Managed by launchd, running from login. macOS integrates the agent with the Keychain: ssh-add --apple-use-keychain ~/.ssh/id_ed25519 stores the passphrase in your login keychain, so the key is available automatically after a reboot without retyping. Add UseKeychain yes and AddKeysToAgent yes under Host * in your config to make that the default.
  • Windows. Modern Windows ships an OpenSSH Authentication Agent service. It’s set to manual start by default, so enable it once: Set-Service ssh-agent -StartupType Automatic; Start-Service ssh-agent in an elevated PowerShell, then ssh-add as usual. Windows stores the loaded keys in the registry, protected for your account.

The common thread: you almost never run ssh-agent yourself. You run ssh-add, and the OS-provided agent holds the result.

Agent forwarding, and why it’s the risky part

ssh -A — agent forwarding — extends the agent’s reach to a remote host. It opens a socket on the server you connect to that proxies signing requests back to your local agent, so a process there (another ssh, a git pull) can authenticate as you to the next hop. The key still never leaves your laptop, which sounds safe — but you’ve exposed live use of it on a machine you may not fully control. Anyone with root on that host can reach the forwarded socket and sign as you, for as long as your session is open. It’s a real tool with a real footgun, and it deserves its own read: agent forwarding is convenient and dangerous.

The agent socket is a signing oracle

Here’s the property to internalize, because it’s the whole security model in one sentence: the agent’s socket is a live signing oracle, and any process that can reach it can ask it to sign. The agent does not authenticate who is asking — it signs for whoever holds the socket path in SSH_AUTH_SOCK. On your own machine that’s fine; the socket sits in a private per-user directory only you can read. The danger is the confused-deputy shape: when the socket is reachable by something you didn’t intend — a forwarded agent on a shared bastion, a compromised process running as your user — that thing can authenticate as you to every server your keys reach, without ever seeing the key.

Two habits follow. Use -t so keys don’t outlive their usefulness in memory, and use -c (or don’t forward at all) when the socket might be reachable by anyone but you. The key never leaking is only half the guarantee; controlling who can use it is the other half.

How Termalin applies the same model

Termalin has a built-in key agent that follows exactly this design, with the rough edges smoothed off. You unlock your keys once; the agent holds them and signs on your behalf, so the private key never touches disk in plaintext and there’s no separate OS agent service to configure. Because it speaks the standard ssh-agent protocol, git and your CLI can sign through it too — it slots into your existing tools rather than replacing them. Passphrases are cached on your terms, with a re-lock timeout, which is the ssh-add -t idea made a default instead of a flag you have to remember. And when the thing signing is an AI agent rather than you, the same custody idea goes further — the agent gets scoped, watched signing without ever holding a key — which is the SSH end of the pattern behind MCP servers. Whichever key you generate (Ed25519 unless something old forces your hand), the agent’s job is the same: unlock once, sign many, and never let the secret leave.


Termalin is a free, cross-platform SSH client with a one-unlock key agent that git and your CLI can sign through — download it, or read how it handles your keys safely.

Try it on one host.

Termalin is a fast SSH client for you — and your agents.

Free tier · 14-day Pro trial · pricing