This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
# Build with Go
go build -o ssh-union-agent .
# Build with Nix
nix build
./result/bin/ssh-union-agent
# Enter development shell (provides Go)
nix develop
# Run tests
nix develop --command go test -v ./...This is a single-file Go application (main.go) implementing an SSH agent multiplexer. The UnionAgent struct implements golang.org/x/crypto/ssh/agent.ExtendedAgent by forwarding requests to multiple upstream SSH agent sockets.
Request routing strategy:
- List/Signers: Aggregates from all upstream agents, deduplicating by key blob
- Sign: Tries each upstream in order until one succeeds
- Add: Forwards only to the first upstream agent
- Remove/Lock/Unlock: Broadcasts to all upstream agents
- Extension: Tries each upstream until one succeeds
The agent creates a Unix socket (auto-generated in $TMPDIR/ssh-XXXXXXXXXX/agent.<ppid> or user-specified) and outputs SSH_AUTH_SOCK and SSH_AGENT_PID in shell-eval format for use with eval $(ssh-union-agent ...).
Tests use agent.NewKeyring() from golang.org/x/crypto/ssh/agent to create real in-memory SSH agent backends served over Unix sockets. This tests actual protocol behavior rather than mocking interfaces.
Note: Tests create temp directories directly in /tmp with short names (e.g., /tmp/ua-abc123/) to avoid Unix socket path length limits (108 chars on Linux). This is necessary because t.TempDir() paths can exceed this limit in nested nix shells.