A few weeks ago I shelved my “homemade Bitwarden” and moved to 1Password on the family plan. Yes, you have to pay, but sharing with the family and the ease of use make up for it. Shortly after migrating the passwords I ran into the Developer tab and its SSH agent: private keys live in the vault, they sync themselves across my machines, and every use is authorized with a fingerprint or with Windows Hello.
By the way, I later found out that Bitwarden has had an SSH agent too since early 2025. You learn something new every day.
It sounded too good to be true, so I set out to check whether it fit my case: several workstations (macOS, Windows, Linux), lots of servers, network gear with SSH from another era, and more and more scripts and AI agents running ssh without me being at the keyboard. In this post I go through what I learned, how I set it up, and where I do NOT use it.
The problem
I’ve been using SSH keys since the last century, and over the years the whole thing has got out of hand. Three machines, each with its “equivalent” ~/.ssh/config holding dozens of destinations, and on each one a handful of private keys that are supposedly the same but that I sync by hand and every now and then discover are not.
The destinations are not few either: servers and virtual machines at home, old network gear, the odd server on the Internet, relatives’ homes I reach over VPN and, from time to time, customer servers where I’m a guest and they impose their own key on me.
And then there’s how I use them: interactive sessions, scripts, and for a while now AI agents in the terminal that call the system ssh without me typing anything.
The question was simple: does the 1Password SSH agent hold up to all of this, or is it going to leave me stranded at the first hurdle?
Short answer: yes, it holds up, and I’m keeping it. For everything I do while I’m at the keyboard, including scripts and AI agents launched from my terminal, it works beautifully. The only thing I leave out is what runs on its own with nobody around (cron, CI runners), which stays on well-restricted file-based keys.
How it works
A quick refresher. When ssh connects to a server, the first thing they do is set up an encrypted channel and agree on a session identifier, a value unique to that connection. Only then does authentication begin, which with public key takes two rounds: the client offers a public key and asks “do you accept this one?”, and if the server says yes, the client signs the session identifier with the private key and sends the signature. The server checks it against the public key it has in authorized_keys and opens the session.

Two details of this dance matter later on. One: the client offers keys in order, and every “I don’t accept it” counts as a failed attempt against the server’s limit, which by default is six. Two: the private key is only used for signing, so an agent that asks for confirmation asks you just once, for the key the server has already accepted.
With 1Password the only thing that changes is who signs. The 1Password agent speaks the standard ssh-agent protocol, so for the OpenSSH client there’s nothing new: when it’s time to sign, ssh asks the agent through a socket (or a named pipe on Windows), 1Password checks that it’s unlocked, asks for your fingerprint if that process didn’t have permission yet, signs inside its own process and returns only the signature.

The private key never leaves 1Password: it’s not on disk unencrypted, it’s not loaded into the memory of ssh or your shell, and with the vault locked the agent doesn’t even have it in memory.
Compared with the usual suspects
The good old ssh-agent loads the decrypted key into memory once and never asks again. Convenient, but the key still lives in a file on every machine and syncing is your problem. gpg-agent does something similar with a lot more ceremony; I used it for years and I don’t miss it. Hardware keys (YubiKey and friends) isolate the key best of all, but every device is a different key and you have to touch the key on every operation. SSH certificates with a CA are the “enterprise” solution, and for a homelab it’s using a sledgehammer to crack a nut.
1Password sits at a very reasonable middle ground: isolation, biometric authorization per use, automatic sync and zero private files on disk. In exchange, it needs the desktop app open and unlocked. And that’s the catch.
Where I use it and where I don’t
It’s not “all or nothing”. The 1Password agent takes care of:
- Interactive sessions to any destination.
- Scripting from the workstation, including heredocs and pipes with
tar. - The AI agents I launch from an unlocked desktop session.
- Everything that is Git over SSH.
And the classic file-based keys keep everything that has nobody in front of a screen: cron, systemd timers, CI runners and scripts that run on a server without a user session. For those cases the key lives on disk and, above all, is restricted in the destination’s authorized_keys with command="..." and no shell, no port forwarding and no agent forwarding. A key with no person behind it that can only run one specific script is an acceptable risk; one with a full shell is not.
This isn’t some exotic limitation of 1Password: any agent that asks a person for authorization fails in exactly the same way when there’s no person.
How many keys?
There are four reasonable strategies. One for everything is the most convenient and the worst idea: if it gets compromised, you have to change it on every server the same day. One per host is the opposite extreme: revoking is trivial, but with dozens of destinations the maintenance is hell. One per machine is what I had before, and with 1Password it stops making sense, because the key is no longer tied to the machine. And one per purpose: group destinations by trust domain, so that if a key falls the damage stays within that group.
I’m going with the last one. I ended up with six:
| Key | Type | Destinations |
|---|---|---|
Homelab | ed25519 | Servers, VMs and containers at home |
Network | ed25519 | Network gear with current firmware |
Network Legacy | RSA | Old switch that only understands ssh-rsa |
VPS | ed25519 | Virtual machines in the cloud |
Clientes | ed25519 | Relatives’ homes and customers who accept my key |
Git | ed25519 | Forgejo and GitHub (and signing commits, if you want) |
Having few keys also has a practical advantage: not hitting the server’s limit of six attempts. It happened to me on day one: eight keys in the agent, the right one at the end, and a Too many authentication failures. Ten seconds of panic and a lesson well learned.
I avoid it in two ways, and I use both. From the client, with IdentitiesOnly yes on every Host and an IdentityFile pointing to the public key (.pub) downloaded from 1Password and stored in ~/.ssh/keys/. OpenSSH lets you specify just the public key to use the matching private key from the agent, so ssh asks for that key and no other. From the agent, with the agent.toml file, where the order of the blocks is the order in which the keys are offered:
agent.toml — key order and visibility
# Fichero de configuración del agente SSH de 1Password.
#
# Linux y macOS: ~/.config/1Password/ssh/agent.toml
# (o $XDG_CONFIG_HOME/1Password/ssh/agent.toml)
# Windows: %LOCALAPPDATA%\1Password\config\ssh\agent.toml
#
# Cada bloque [[ssh-keys]] es un filtro (item AND vault AND account).
# El ORDEN de los bloques es el orden en que el agente ofrece las claves
# a los servidores: las de uso más frecuente, primero.
#
# Ojo: en cuanto este fichero existe, deja de aplicarse la regla por
# defecto ("todas las claves SSH del vault Personal"). Solo se ofrecen
# las que listes aquí. Un error de sintaxis para el agente y lo verás
# en Settings > Developer.
#
# El campo vault es opcional; si el nombre no coincide exactamente, el agente
# se queda sin claves. Con el título del item basta. Fichero POR MÁQUINA.
[[ssh-keys]]
item = "SSH Homelab"
[[ssh-keys]]
item = "SSH Git"
[[ssh-keys]]
item = "SSH VPS"
[[ssh-keys]]
item = "SSH Network"
[[ssh-keys]]
item = "SSH Network Legacy"
# Clave para casas de familiares y clientes que sí permiten usar la mía. Los que me obligan a
# usar la suya van por fichero con "IdentityAgent none" en ~/.ssh/config.
[[ssh-keys]]
item = "SSH Clientes"
Two warnings about this file. As soon as it exists, only the keys listed are offered. And it’s a per-machine file: it doesn’t travel with the vault, you have to copy it to every computer.
Setting it up on each machine
It starts the same way everywhere: Settings > Developer > Use the SSH Agent. As soon as you enable it, 1Password asks whether it may store the key names on disk; I say yes, because an item’s name is not a secret and that way the authorization prompt says “SSH Homelab” instead of a truncated fingerprint. And in Settings > General, on all three platforms, I leave 1Password in the menu bar or tray and starting at login: if you close the app, the agent dies with it.
What changes per system is where the agent listens and which SSH client talks to it.
macOS. The agent listens on a socket inside the 1Password folder, and the app offers to edit ~/.ssh/config to point to it. My recommendation: don’t let it. Copy the snippet and put it in a separate file that gets included at the end of the config, for a reason I explain in the next section. And if you use ControlMaster, remember that connections already open don’t re-authenticate: to really test it, ssh -o ControlPath=none host.
Linux. The socket is ~/.1password/agent.sock. Two warnings: the agent does not work with the Flatpak or Snap installs, so install 1Password from its repository, as I describe in Linux for development; and if you use GNOME, its keyring already exports an SSH_AUTH_SOCK that can override 1Password’s. That’s why I prefer IdentityAgent in the config to fighting environment variables.
Windows 11. There’s no socket here: 1Password listens on the same named pipe that Microsoft’s native OpenSSH uses. That’s why you have to disable the “OpenSSH Authentication Agent” service before enabling 1Password’s (the app itself asks you to), and that’s why the Windows ssh.exe uses the 1Password agent for every host without configuring anything. I installed it back in the day exactly as I describe in Windows for development.
Git Bash is another story: its ssh doesn’t know how to talk to named pipes. The fix is to use Microsoft’s from there too, with core.sshCommand in Git pointing to the full path C:/Windows/System32/OpenSSH/ssh.exe and prepending that directory to the PATH in ~/.bashrc, because Git for Windows puts its own directories first at startup.
WSL. The official route is to delegate to the Windows ssh.exe with a few aliases, with two consequences: the Windows ~/.ssh/config is used, not WSL’s, and every new tab asks for approval again. The alternative I use is a bridge with socat and npiperelay that creates the socket at ~/.1password/agent.sock, the same place as on Linux, so that the same config works on both:
~/.local/bin/1password-agent-relay.sh — WSL → 1Password bridge
#!/usr/bin/env bash
# Puente WSL -> agente SSH de 1Password en Windows (opción B, NO documentada
# por 1Password; ellos solo la citan como "workaround con npiperelay y socat").
#
# Requisitos:
# - En WSL: sudo apt install -y socat
# - En Windows: npiperelay.exe (fork mantenido: github.com/albertony/npiperelay)
# descárgalo de Releases y ponlo en una ruta fija, por ejemplo
# C:\tools\npiperelay.exe
#
# Uso: añade a ~/.bashrc o ~/.zshrc:
# source ~/.local/bin/1password-agent-relay.sh
#
# El socket se crea en ~/.1password/agent.sock a propósito: así el mismo
# ~/.ssh/config.d/linux.conf del Linux de escritorio funciona en WSL sin tocarlo.
NPIPERELAY="/mnt/c/tools/npiperelay.exe"
export SSH_AUTH_SOCK="$HOME/.1password/agent.sock"
if [ ! -x "$NPIPERELAY" ]; then
echo "1password-agent-relay: no encuentro $NPIPERELAY" >&2
return 1 2>/dev/null || exit 1
fi
# Si no hay ya un socat escuchando en ese socket, lo levanto.
if ! ss -xl 2>/dev/null | grep -q "$SSH_AUTH_SOCK"; then
rm -f "$SSH_AUTH_SOCK"
mkdir -p "$(dirname "$SSH_AUTH_SOCK")"
chmod 700 "$(dirname "$SSH_AUTH_SOCK")"
(setsid socat \
UNIX-LISTEN:"$SSH_AUTH_SOCK",fork,umask=077 \
EXEC:"$NPIPERELAY -ei -s //./pipe/openssh-ssh-agent",nofork &) >/dev/null 2>&1
fi
To check that the agent responds, on any of the platforms, ssh-add -l should list the keys in the vault.
One config for all three machines
My goal was to have a single ~/.ssh/config, identical on all three machines, where the only thing that changes per platform is the agent’s path. The solution is a base file plus an Include config.d/*.conf, where on each machine only its platform file exists.
~/.ssh/config — identical base on all three machines
# ~/.ssh/config — fichero BASE, idéntico en Linux, Windows 11 y macOS.
#
# Regla de oro de ssh_config: para cada opción gana el PRIMER valor que
# encuentra. Por eso lo específico va arriba y lo general (Host * y el
# Include con el IdentityAgent de cada plataforma) va al final.
#
# Las claves privadas viven en 1Password. Aquí solo hay ficheros .pub
# descargados de la app, en ~/.ssh/keys/, para que IdentitiesOnly sepa
# qué clave pedirle al agente en cada destino.
# ------------------------------------------------------------------
# Homelab: clave "Homelab" (ed25519)
# ------------------------------------------------------------------
Host pve
HostName 192.168.1.10
User root
Host router
HostName 192.168.1.1
User luis
Host dockervm
HostName 192.168.1.20
User luis
Host npm
HostName 192.168.1.21
User root
Host haos
HostName 192.168.1.30
User root
Host pve router dockervm npm haos
IdentityFile ~/.ssh/keys/homelab.pub
IdentitiesOnly yes
# ------------------------------------------------------------------
# Equipos de red: "Network" (ed25519) para el controlador y lo moderno;
# "Network Legacy" (RSA) solo para el switch antiguo que exige ssh-rsa.
# ------------------------------------------------------------------
Host wlc
HostName 192.168.1.5
User admin
IdentityFile ~/.ssh/keys/network.pub
IdentitiesOnly yes
Host sw-core
HostName 192.168.1.2
Host sw-planta1
HostName 192.168.1.3
Host sw-planta2
HostName 192.168.1.4
Host ap-salon
HostName 192.168.1.41
# Firmware antiguo: solo firma ssh-rsa (SHA-1) y KEX antiguos.
# OpenSSH >= 8.8 los desactiva por defecto; aquí los reactivo SOLO
# para estos hosts.
Host sw-core sw-planta* ap-*
User admin
IdentityFile ~/.ssh/keys/network-legacy.pub
IdentitiesOnly yes
HostKeyAlgorithms +ssh-rsa
PubkeyAcceptedAlgorithms +ssh-rsa
KexAlgorithms +diffie-hellman-group14-sha1
# ------------------------------------------------------------------
# VPS en la nube (AWS, GCP, OVHcloud...): clave "VPS" (ed25519)
# ------------------------------------------------------------------
Host vps
HostName vps.midominio.com
User debian
IdentityFile ~/.ssh/keys/vps.pub
IdentitiesOnly yes
# ------------------------------------------------------------------
# Familiares y clientes que aceptan mi clave: clave "Clientes" (ed25519)
# ------------------------------------------------------------------
# Casa de un familiar, detrás de un túnel OpenVPN y con puerto no estándar.
Host casa-familiar-1
HostName 10.8.0.50
Port 2222
User luis
IdentityFile ~/.ssh/keys/clientes.pub
IdentitiesOnly yes
# Otro familiar, saltando a través del VPS sin reenviar el agente al intermedio.
Host casa-familiar-2
HostName 10.8.0.60
Port 2222
User luis
ProxyJump vps
IdentityFile ~/.ssh/keys/clientes.pub
IdentitiesOnly yes
# ------------------------------------------------------------------
# Clientes que imponen su clave: fichero, fuera de 1Password
# ------------------------------------------------------------------
Host cliente-acme
HostName bastion.acme.example
User invitado
IdentityAgent none
IdentityFile ~/.ssh/clientes/acme_ed25519
IdentitiesOnly yes
# ------------------------------------------------------------------
# Git: clave "Git" (ed25519, también firma commits)
# ------------------------------------------------------------------
Host github.com
User git
IdentityFile ~/.ssh/keys/git.pub
IdentitiesOnly yes
Host forgejo.midominio.com
User git
Port 22
IdentityFile ~/.ssh/keys/git.pub
IdentitiesOnly yes
# ------------------------------------------------------------------
# Valores por defecto para todo lo demás
# ------------------------------------------------------------------
Host *
ForwardAgent no
AddKeysToAgent no
ServerAliveInterval 60
ServerAliveCountMax 3
HashKnownHosts yes
# Lo que cambia por plataforma (el IdentityAgent) vive en config.d/.
# Va al FINAL para que un "IdentityAgent none" de arriba gane.
Include config.d/*.conf
~/.ssh/config.d/macos.conf
# ~/.ssh/config.d/macos.conf — solo existe en el Mac.
# Socket del agente SSH de 1Password en macOS.
Host *
IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"
~/.ssh/config.d/linux.conf (also on WSL with the bridge)
# ~/.ssh/config.d/linux.conf — solo existe en el Linux (y en WSL, ver post).
# Socket del agente SSH de 1Password en Linux.
Host *
IdentityAgent ~/.1password/agent.sock
~/.ssh/config.d/windows.conf
# ~/.ssh/config.d/windows.conf — solo existe en Windows 11.
#
# Aquí no hay IdentityAgent: el OpenSSH de Microsoft habla siempre con el
# named pipe \\.\pipe\openssh-ssh-agent, y 1Password se pone a escuchar
# en ese pipe cuando activas el agente. No admite IdentityAgent, así que
# el agente de 1Password se usa para TODOS los hosts (salvo los que lleven
# IdentityAgent none, que sigue funcionando).
Three decisions that deserve an explanation:
The Include goes at the end. It’s the opposite of what you’ll see in almost every example, but in ssh_config the first value found for each option wins. If the global IdentityAgent were at the top, the customers’ IdentityAgent none would never apply. Specific at the top, general at the bottom. And watch out: an Include that comes after a Host block belongs to that block, which is why the Host * with the defaults goes right before it. If ssh -G destination doesn’t show you identityagent, this is why.
Keys that aren’t in 1Password. For the customers who impose their own key, the block carries IdentityAgent none and an IdentityFile pointing to the file-based key. ssh doesn’t even ask the agent. It works on all three platforms, Windows included.
ForwardAgent off. Forwarding the agent leaves a socket on the intermediate host that anyone with root there can use for as long as your session lasts. With 1Password the damage is limited to whatever you authorize at that moment, but I prefer ForwardAgent no and, when I have to hop through an intermediate host, ProxyJump, which opens a second connection from my machine without exposing anything on the hop.
The old network gear has its own block that re-enables ssh-rsa, and I cover it in the server section.
Git
With SSH sorted, Git comes almost for free: the Host entries for GitHub and for my Forgejo use the Git key with IdentitiesOnly yes. If you have several accounts, the host alias trick I described in Multi-account Git still holds, each alias with its own .pub.
And if you want to sign commits, since Git 2.34 you can do it with SSH keys instead of GPG, and 1Password ships its own signer. The shared .gitconfig ends up like this, moving what changes per system, which is the signer’s path, out to a local file:
~/.gitconfig — shared across all three machines
# ~/.gitconfig — parte COMÚN a las tres máquinas.
# Lo que depende del sistema operativo (ruta de op-ssh-sign y, en
# Windows, el ssh.exe de Microsoft) vive en ~/.gitconfig.local.
[user]
name = Luis Palacios
email = tu@correo.com
# Clave PÚBLICA completa del item "SSH Git" de 1Password.
signingkey = ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
[gpg]
format = ssh
[gpg "ssh"]
allowedSignersFile = ~/.ssh/allowed_signers
[commit]
gpgsign = true
[tag]
gpgsign = true
[include]
path = ~/.gitconfig.local
Note that user.signingkey is the full public key, not a path. The most reliable way to get the local part is to open the key’s item in the app, click Configure Commit Signing and copy the snippet it generates for your system. I don’t sign commits myself, by the way: I leave it here in case you’re interested.
Scripts and AI agents
This is where the decision was really at stake. What rules here are two settings in Settings > Developer: when it asks (by default, once per application and key, and “application” includes its subprocesses, so authorizing the terminal covers the ssh that an AI agent launches from inside it) and how long it remembers (by default, until 1Password locks; it can be extended to a number of hours).
And one thing you need to be clear about: BatchMode=yes disables ssh’s own prompts, not the 1Password dialog, which is a different application. So there are three scenarios:
- 1Password unlocked and the terminal already authorized. Everything works without any prompt. This is the normal case.
- 1Password locked. The agent throws up an unlock prompt and
sshsits there waiting. The script, or the AI agent, looks hung until you unlock. - Request from an app that isn’t in the foreground. 1Password doesn’t bother you with the prompt and leaves the request pending; you see it as SSH request waiting on the tray icon. This is the one that has most often made me think the AI agent had hung.
My checklist so that nothing hangs:
- 1Password open and unlocked.
- Before letting the AI agent loose, a manual
sshfrom that same terminal to authorize the application and the key. - For long sessions, extend how long the approval is remembered.
- If an SSH command goes more than a few seconds without output, look at the 1Password icon before killing anything.
IdentitiesOnly yeson everyHost: a single prompt per connection, not five.- None of this applies to cron or runners. Those go with a file-based key and
command=.
Server side
Good news: on Linux servers there’s nothing to change, because the signatures 1Password produces are normal OpenSSH signatures. The only thing I do is take the chance to tidy up the authorized_keys: a comment on each line saying which key it comes from, remove the keys of machines that no longer exist, and make sure the server doesn’t allow password logins.
Three special cases:
Virtual machines in the cloud. The authorized_keys isn’t entirely yours: the provider’s agent writes it from the instance or project metadata, and whatever you add by hand disappears at the next sync. The new key gets added where the others live, with the provider’s tool.
Windows as a server. If the user is an administrator, the keys don’t go in their authorized_keys but in C:\ProgramData\ssh\administrators_authorized_keys. Check sshd_config before pasting the key in the wrong place. And one more thing: from an SSH session into that Windows box, the 1Password agent is not available, because it only serves processes from your desktop session. To hop from there to somewhere else, you have to be at the keyboard.
Old network gear. My main switch runs firmware from more than a decade ago and as a user key it only understands ssh-rsa. That’s why the Network Legacy key is RSA (1Password imports RSA keys without any trouble) and that’s why its block in the config re-enables ssh-rsa and an old key exchange, which OpenSSH disabled by default years ago. On the switch, the key is registered by its MD5 fingerprint, computed with ssh-keygen -l -E md5 on the downloaded .pub. A warning: the agent signs with SHA-1 while leaving a complaint in its log, and there have been versions of 1Password where it stopped doing so. If one day your old gear stops letting you in right after an update, you know where to start looking.
The wireless controller, with current firmware, is another world: it accepts ed25519 and modern ciphers, so it uses the normal Network key and needs no exception at all.
Security
Before trusting it I wanted to understand what it protects me from and what it doesn’t. A malicious local process can write to the socket, and the protection is the prompt: 1Password tells you which process is asking for which key and you approve or deny. If one shows up that you weren’t expecting, Deny and go investigate. Someone with root on my machine, with file-based keys, walks off with them, full stop; with 1Password there’s nothing on disk to take, and they’d have to wait for me to unlock and approve. It’s not invulnerable, but the bar goes up a lot. And a compromised intermediate host with the agent forwarded can use it for as long as the session lasts, hence ForwardAgent no and ProxyJump.
My hardening checklist:
- Biometric authorization enabled.
- 1Password auto-locks after a few minutes of inactivity and when the screen locks.
- Approvals that are forgotten on lock, except for long sessions with AI agents.
ForwardAgent noandIdentitiesOnly yeson everyHost.agent.tomlso the agent only offers what it’s supposed to offer.- Review the agent’s Activity tab in the app every now and then.
Migrating from files
I did it in four steps, without rushing and without deleting anything until the end.
Inventory. On each machine, which private keys there are and which Host in the config uses them. With that I built a table: file, machine, destinations.
Regenerate or import. For everything modern I generated new ed25519 keys inside 1Password, so the private key has never existed on a disk. For the old switch I imported the RSA key I already had. For the customers, each one according to their rules.
Testing in parallel. I downloaded the .pub files to ~/.ssh/keys/ and, host by host, always the same recipe: upload the new public key using the old key; log in forcing only the new one with ssh -o IdentitiesOnly=yes -i ~/.ssh/keys/homelab.pub host; if it gets in, remove the old one from authorized_keys keeping a copy; point the config block to the new .pub; and finally ssh host without forcing anything. Five minutes per host and no scares.
Retire and delete. Before deleting anything, I moved the private keys no Host referenced any more into a ~/.ssh/retired/ directory and gave them a few days’ grace. I also took the chance to pull out of the config the passwords I had jotted down in comments; they now live in 1Password, which is where they belonged. Then, gone. What really protects them is that all three disks are encrypted.
Common problems
| Error | Cause | Fix |
|---|---|---|
Could not open a connection to your authentication agent | IdentityAgent points to a socket that doesn’t exist, or 1Password isn’t running | Check the socket and that the agent is enabled under Developer |
invalid format on a .pub, then it asks for a password | 1Password is closed: with no agent, ssh tries to read the .pub as a private key | Open 1Password; the warning goes away on its own |
Too many authentication failures | The agent offers more than six keys | IdentitiesOnly yes with the .pub, and order agent.toml |
agent refused operation | 1Password refused to sign: request denied, vault locked or a regression with ssh-rsa | Check the prompt, update 1Password |
no matching key exchange method found | The destination only offers old algorithms | Re-enable them only for that Host |
Permission denied (publickey) with IdentitiesOnly | The .pub doesn’t match any key in the agent, or that key isn’t in agent.toml | ssh-add -l and compare fingerprints |
ssh hung with no output from a script or AI agent | 1Password locked or prompt suppressed because it’s in the background | Unlock and look for SSH request waiting on the icon |
| Nothing works in Git Bash | It’s using its own ssh, which doesn’t talk to the pipe | core.sshCommand and PATH to the Windows ssh.exe |
Conclusion
I love it. The feeling of opening any of the three machines, typing ssh pve, touching the sensor and being in, without having copied a single file, is one of those you don’t go back from. And the prompt that tells you who is asking for which key is a control I didn’t have with ssh-agent.
But it’s important to be clear about the limit: the 1Password agent is for people. Everything that runs on its own, with nobody around, stays on well-restricted file-based keys. And AI agents are somewhere in between: they work beautifully as long as you’re there with the vault unlocked, and they stare into the void as soon as you’re not.
References
Consulted on 4 September 2026. Anything I’ve claimed in this post that doesn’t appear here, take it as my own experience or opinion.