KeePassXC SSH Agent
keepassxc-ssh-agent is a cross-platform (macOS and Linux) SSH IdentityAgent proxy that automatically triggers KeePassXC database unlock (via TouchID / Quick Unlock on macOS, biometric / password unlock on Linux) when an SSH key is needed.
Similar to how Strongbox handles SSH keys, this tool sits between your SSH client and the system ssh-agent. When SSH requests a key that isn't loaded (because the KeePassXC database is locked), the proxy triggers KeePassXC's unlock dialog. After you authenticate with TouchID, KeePassXC pushes the keys to ssh-agent, and the SSH operation continues seamlessly.
KeePassXC SSH Agent based on KeePassXC Browser API.
Prerequisites
- macOS or Linux (uses Unix sockets and KeePassXC's browser extension socket; on Linux the socket path is resolved from
XDG_RUNTIME_DIR, supporting native and Flatpak installs) - Python >= 3.10
- KeePassXC with:
- Browser Integration enabled (Settings > Browser Integration > Enable browser integration)
- SSH Agent Integration enabled (Settings > SSH Agent > Enable SSH Agent integration)
- SSH keys configured with "Add key to agent when database is opened/unlocked"
- Browser Integration enabled (Settings > Browser Integration > Enable browser integration)
Usage
usage: keepassxc-ssh-agent [-h] [--socket SOCKET] [--config CONFIG]
[--timeout TIMEOUT] [-v]
{install,run,status,uninstall} ...
SSH IdentityAgent proxy that triggers KeePassXC database unlock via TouchID
positional arguments:
{install,run,status,uninstall}
install Associate with KeePassXC and set up the auto-start service
run Start the SSH agent proxy (default command)
status Check connection status with KeePassXC
uninstall Remove the auto-start service and restore SSH_AUTH_SOCK
options:
-h, --help show this help message and exit
--socket SOCKET Path for the agent Unix socket
(default: ~/.keepassxc/agent.sock)
--config CONFIG Path to config file
(default: ~/.keepassxc/ssh-agent.json)
--timeout TIMEOUT Timeout in seconds for unlock prompt (default: 30)
-v, --verbose Enable verbose logging
How It Works
SSH Client ──► SSH agent protocol ──► keepassxc-ssh-agent (proxy)
│
├─► SSH agent protocol ──► System ssh-agent
│ (forward requests / replay after unlock)
│
└─► Browser extension protocol ──► KeePassXC
(trigger unlock when keys missing)
- SSH client connects to the proxy socket and requests identities or a signature
- Proxy forwards the request to the system
ssh-agent - If
ssh-agentreturns keys/signature, proxy passes it through (no delay) - If
ssh-agentreturns empty/failure (DB is locked, keys not loaded):- Proxy connects to KeePassXC via the browser extension protocol
- Sends
get-databasehashwithtriggerUnlockto show the unlock dialog - Polls until the database is unlocked or timeout expires
- KeePassXC pushes SSH keys to
ssh-agenton unlock (asynchronously) - Proxy then polls
ssh-agentuntil the key appears (rather than retrying once), so the very first request succeeds, and returns the result
SSH_AUTH_SOCK Interception
The proxy automatically intercepts SSH_AUTH_SOCK on startup by renaming the system ssh-agent socket (e.g. /tmp/com.apple.launchd.XXX/Listeners on macOS, /run/user/UID/ssh-agent.socket on Linux) to a .system backup and placing a symlink from the original path to the proxy socket. All SSH clients then connect to the proxy transparently. The proxy forwards requests to the renamed .system socket.
On shutdown, the proxy restores the original socket. No separate service or SSH config is needed — the run command handles everything.
Note (Linux/systemd): a systemd
--userservice starts with a clean environment and does not inherit your shell'sSSH_AUTH_SOCK.installtherefore captures the currentSSH_AUTH_SOCKand bakes it into the generated unit (Environment=SSH_AUTH_SOCK=...) so interception works without any shell-profile changes.
Install
Make sure KeePassXC is running and unlocked with browser integration enabled, then:
Homebrew (macOS, recommended)
See homebrew homepage on how to setup homebrew.
brew install mietzen/tap/keepassxc-ssh-agent
keepassxc-ssh-agent install --register-only
brew services start keepassxc-ssh-agent
This will:
- Install
keepassxc-ssh-agentand its dependencies - Register with KeePassXC (you'll need to approve the association in the unlocked KeePassXC window)
- Start the background service via Homebrew (auto-starts on login)
pipx - Automatic Install (macOS and Linux)
See pipx installation guide on how to setup pipx.
pipx install keepassxc-ssh-agent
keepassxc-ssh-agent install -y
This will:
- Generate encryption keys for the browser protocol
- Request association with KeePassXC (you'll need to approve it in the KeePassXC window)
- Save the agent configuration to
~/.keepassxc/ssh-agent.json - Save the browser API credentials to
~/.keepassxc/browser-api.json(shared withkeepassxc-cliif installed) - Set up an auto-start service for login: a LaunchAgent on macOS, or a systemd user service (
~/.config/systemd/user/keepassxc-ssh-agent.service) on Linux
The -y flag auto-accepts all prompts. Without it, you'll be asked interactively whether to set up the auto-start service.
On Linux, manage the service with systemctl --user:
systemctl --user status keepassxc-ssh-agent # check status
systemctl --user restart keepassxc-ssh-agent # restart
journalctl --user -u keepassxc-ssh-agent # view logs
systemd
--userservices require an active user session. On headless machines (no graphical login), enable lingering so the service starts at boot:loginctl enable-linger $USER.
pipx - Manual Install
If you want more control over the installation, you can split it into steps:
1. Install the package
pipx install keepassxc-ssh-agent
2. Register with KeePassXC
Register with KeePassXC without setting up the auto-start service:
keepassxc-ssh-agent install --register-only
You'll need to approve the association in the KeePassXC window when prompted.
3. Set up auto-start (optional)
macOS — create a LaunchAgent plist:
cat << 'EOF' > ~/Library/LaunchAgents/org.keepassxc.ssh-agent.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>org.keepassxc.ssh-agent</string>
<key>ProgramArguments</key>
<array>
<string>/path/to/keepassxc-ssh-agent</string>
<string>run</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/keepassxc-ssh-agent.out.log</string>
<key>StandardErrorPath</key>
<string>/tmp/keepassxc-ssh-agent.err.log</string>
</dict>
</plist>
EOF
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/org.keepassxc.ssh-agent.plist
Replace /path/to/keepassxc-ssh-agent with the actual path (find it with which keepassxc-ssh-agent).
Linux — create a systemd user unit:
mkdir -p ~/.config/systemd/user
cat << EOF > ~/.config/systemd/user/keepassxc-ssh-agent.service
[Unit]
Description=KeePassXC SSH Agent proxy
After=ssh-agent.service
[Service]
Type=simple
ExecStart=$(which keepassxc-ssh-agent) run
Environment=SSH_AUTH_SOCK=${SSH_AUTH_SOCK}
Restart=on-failure
[Install]
WantedBy=default.target
EOF
systemctl --user daemon-reload
systemctl --user enable --now keepassxc-ssh-agent.service
The Environment=SSH_AUTH_SOCK=... line captures your current agent socket so the proxy can intercept it (the service otherwise runs with a clean environment).
Or start manually without an auto-start service:
keepassxc-ssh-agent run
Uninstall
Homebrew (macOS)
brew services stop keepassxc-ssh-agent
brew uninstall keepassxc-ssh-agent
rm -rf ~/.keepassxc # Remove config (optional)
pipx
keepassxc-ssh-agent uninstall -y
pipx uninstall keepassxc-ssh-agent
This stops and removes the auto-start service (LaunchAgent on macOS, systemd user service on Linux), restores the original SSH_AUTH_SOCK socket, and removes the config directory (~/.keepassxc/). Without -y, you'll be asked before deleting the config directory.
Manual Uninstall
1. Stop and remove the auto-start service
macOS:
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/org.keepassxc.ssh-agent.plist 2>/dev/null
rm -f ~/Library/LaunchAgents/org.keepassxc.ssh-agent.plist
Linux:
systemctl --user disable --now keepassxc-ssh-agent.service 2>/dev/null
rm -f ~/.config/systemd/user/keepassxc-ssh-agent.service
systemctl --user daemon-reload
2. Restore SSH_AUTH_SOCK
If the agent was running, it restores the original socket on shutdown automatically. If the system socket is still symlinked (e.g. after a crash), reboot or restore manually:
# Find the original socket path
SYSTEM_AGENT=$(cat ~/.keepassxc/ssh-agent.json | python3 -c 'import json,sys; print(json.load(sys.stdin).get("system_agent_path",""))')
# Remove the symlink and restore the backup
rm -f "$SYSTEM_AGENT"
mv "${SYSTEM_AGENT}.system" "$SYSTEM_AGENT"
3. Remove config and socket
rm -rf ~/.keepassxc
4. Uninstall the package
pipx uninstall keepassxc-ssh-agent
Known Limitations
- macOS and Linux only: Relies on KeePassXC's browser extension Unix socket, whose path is platform-specific (
$TMPDIR/org.keepassxc.KeePassXC.BrowserServeron macOS,$XDG_RUNTIME_DIR/.../org.keepassxc.KeePassXC.BrowserServeron Linux) - Linux auto-start: Uses a systemd
--userservice, which requires an active user session (useloginctl enable-lingerfor headless setups) - DB unlocked but agent cleared: If the database is already unlocked but
ssh-agentkeys were manually removed (ssh-add -D), the proxy detects empty keys and triggers "unlock", but KeePassXC reports "already unlocked" without reloading keys. Workaround: lock and re-unlock the database in KeePassXC. - Multiple databases:
triggerUnlockonly works for the currently active database tab in KeePassXC.
Development
This package depends on keepassxc-browser-api, which handles the KeePassXC browser extension protocol. The browser API credentials are stored in ~/.keepassxc/browser-api.json and are shared with keepassxc-cli if installed.
git clone https://github.com/mietzen/keepassxc-ssh-agent
git clone https://github.com/mietzen/keepassxc-browser-api
cd keepassxc-ssh-agent
python3 -m venv .venv
source .venv/bin/activate
# Install local keepassxc-browser-api dependency first
pip install ../mietzen-keepassxc-browser-api/
# Install with dev dependencies
pip install -e ".[dev]"
# Run tests
pytest --tb=short -q
# Run tests with coverage
pytest --cov=keepassxc_ssh_agent --cov-report=term-missing
# Lint
ruff check --ignore=E501 --exclude=__init__.py ./keepassxc_ssh_agent
Release files for keepassxc-ssh-agent 1.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| keepassxc_ssh_agent-1.6.0.tar.gz | 4.5 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| keepassxc_ssh_agent-1.6.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 4.5 MB
Release files / keepassxc_ssh_agent-1.6.0.tar.gz
| Download URL | keepassxc_ssh_agent-1.6.0.tar.gz |
|---|---|
| Size | 4.5 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
aa9f6bcbf9a863faf59e445fd213900933697c5a3eedffc98fc10faf092bb28a
|
|
BLAKE2b-256 checksum How to use checksums |
7de3ec5966a7165f619e063b37d26a8c55d4c0bf5a2632c081d16005b9c8c6c7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 2, 2026.
Transparency logRelease files / keepassxc_ssh_agent-1.6.0-py3-none-any.whl
| Download URL | keepassxc_ssh_agent-1.6.0-py3-none-any.whl |
|---|---|
| Size | 20.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
17b7ab7f50d7eb037f5fb4219408b1409bf3b0a07c9e4a70f734f2ed94d0bebe
|
|
BLAKE2b-256 checksum How to use checksums |
d56052ab45a0377090a93e0e31c26565ace2e5809195f29dd95439a5b64ccb61
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 2, 2026.
Transparency log