ssh-agent manager compatible with direnv
- Go 98.1%
- Just 1.9%
| .gitignore | ||
| agent.go | ||
| agent_darwin.go | ||
| agent_linux.go | ||
| agent_test.go | ||
| go.mod | ||
| justfile | ||
| main.go | ||
| README.md | ||
sage
A lightweight SSH agent multiplexer. Manage multiple isolated ssh-agent
instances — one per identity — instead of juggling a single global agent.
Install
Requires Go 1.25+ and just.
just install # builds and copies to /usr/local/bin/
Or build manually:
go build -o sage .
Usage
# Start (or reuse) an agent for an identity and set env vars
eval "$(sage load github)"
# Add a key to the running agent (standard ssh-add)
ssh-add ~/.ssh/github_ed25519
# Check what's running
sage status
# Check a specific identity
sage status github
# Remove all keys from an agent (agent keeps running)
sage unload github
# Stop an agent and clean up
sage stop github
# Stop all running agents
sage stop-all
Commands
| Command | Description |
|---|---|
load <identity> |
Ensure agent is running, print export statements |
unload <identity> |
Remove all keys from a running agent |
status [identity] |
Show state of one or all agents |
stop <identity> |
Stop agent process and remove socket/pid files |
stop-all |
Stop all running agents |
version |
Print version |
Flags
| Flag | Default | Description |
|---|---|---|
--lifetime |
8h |
Key lifetime (passed to ssh-agent -t) |
--dir |
~/.ssh/agents |
Directory for socket and PID files |
How it works
Each identity gets two files in ~/.ssh/agents/:
<identity>.sock— the Unix domain socket forSSH_AUTH_SOCK<identity>.pid— the PID of thessh-agentprocess
sage load is idempotent: if an agent for the given identity is already
running, it reuses it. This makes it safe to put in your shell profile:
# ~/.bashrc or ~/.zshrc
eval "$(sage load default)"
Agents run as detached processes (setsid) and survive shell exits. They
are not re-parented to sage — sage is stateless and reads from the
filesystem on each invocation.
Shell integration examples
Multiple identities:
# Load a specific identity before a git operation
eval "$(sage load work)"
git push
# Switch to another
eval "$(sage load personal)"
git push
SSH config integration:
# ~/.ssh/config
Host github.com
IdentityAgent ~/.ssh/agents/github.sock
Platform support
- Linux (
/proc/self/fdfor FD cleanup) - macOS (
/dev/fdfor FD cleanup)