ssh-agent manager compatible with direnv
  • Go 98.1%
  • Just 1.9%
Find a file
2026-04-05 09:21:17 +02:00
.gitignore feat: small ssh-agent wrapper 2026-03-06 14:09:20 +01:00
agent.go fix: harden agent lifecycle and close security gaps 2026-04-05 09:14:23 +02:00
agent_darwin.go fix: harden agent lifecycle and close security gaps 2026-04-05 09:14:23 +02:00
agent_linux.go fix: harden agent lifecycle and close security gaps 2026-04-05 09:14:23 +02:00
agent_test.go fix: harden agent lifecycle and close security gaps 2026-04-05 09:14:23 +02:00
go.mod chore: bump to go 1.26 2026-04-05 09:21:17 +02:00
justfile docs: update readme 2026-04-04 11:23:58 +02:00
main.go fix: harden agent lifecycle and close security gaps 2026-04-05 09:14:23 +02:00
README.md docs: update readme 2026-04-04 11:23:58 +02:00

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 for SSH_AUTH_SOCK
  • <identity>.pid — the PID of the ssh-agent process

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/fd for FD cleanup)
  • macOS (/dev/fd for FD cleanup)