SSH Config
Skill0 starsChanged 4 months agoMITView on GitHub
Set up, repair, upgrade, and optimize ~/.ssh/config and SSH KEY HYGIENE safely (macOS-aware), with a first-class KEYS path — treating private keys as secrets that must NEVER be exposed, committed, or read into the model's context. Use to SET UP a clean structured ~/.ssh/config (global defaults, per-Host blocks, Include, hardening), REPAIR failing auth (loose perms, agent empty, wrong Host match, too-many-failures, known_hosts mismatch), UPGRADE by hardening/modernizing the config and moving off weak key types, OPTIMIZE with a prioritized config + key-hygiene report, or manage KEYS (generate ed25519, add to agent + keychain, per-host identities, rotation, register the PUBLIC key with GitHub). Verified — config resolves and auth actually works.
- Reads credentials
In this repository12 other files it gives its agents.
- Brew DoctorSkill
- Credential StoreSkill
- Dev EnvironmentSkill
- DotfilesSkill
- Ghostty ConfigSkill
- Git SetupSkill
- Identity ProfilesSkill
- macOS DefaultsSkill
- Neovim ConfigSkill
- Runtime VersionsSkill
- Shell SyncSkill
- Terminal ThemeSkill
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 0 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 55
Never
cata private key: Read type/size via ssh-keygen -lf <key>.pub and filenames only. - Very specific: line 63
Private keys are secrets: Only ever surface a key's *filename, type, and permissions* — never its contents.
- Very specific: line 80
Read ~/.config/devenv/config.toml before prompting.
- Very specific: line 93
Don't break working auth: Test the new config resolves (ssh -G) and authenticates (ssh -T) before removing a Host or deleting a key.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
SSH config & key hygiene
Manage ~/.ssh/config and SSH key hygiene on macOS, with one non-negotiable rule: a private
key is a secret — never print it, never commit it, never expose it. This skill is
verification-first: prove the config resolves (ssh -G) and auth actually works (ssh -T)
rather than just editing the file and hoping.
Route to a workflow
| The user wants to… | Workflow |
Build a clean, structured ~/.ssh/config | reference/setup.md |
| Fix failing auth — key not offered, agent empty, wrong Host match | reference/repair.md |
| Harden / modernize the config, move off weak key types | reference/upgrade.md |
| Review config + key hygiene, prioritized | reference/optimize.md |
| Generate / add / rotate keys, register with GitHub | reference/keys.md |
| Prove config resolves and auth works | reference/verification.md |
reference/keys.md is a first-class path (key generation/rotation is a distinct security flow), kept alongside the canonical four.
The scripts (call these; don't re-derive them)
scripts/ is the stable toolbox — see scripts/README.md. Call a script by
name instead of re-deriving stat / ssh-keygen / ssh -G / ssh-add each session; the
secrets discipline is baked in (no script ever emits private-key bytes — metadata only).
| Script | Does | Read-only? |
scripts/ssh_config_audit.py [host] | config perms + Host aliases + Include + hardening opts + weak settings + known_hosts; with [host], the ssh -G effective config | ✅ |
scripts/key_audit.py [ssh-dir] | per key: perms, type, bits, comment, fingerprint, passphrase?, in-agent?, strength verdict | ✅ |
scripts/agent_status.py [ssh-dir] | ssh-add -l identities cross-referenced against on-disk *.pub | ✅ |
scripts/key_new.py <name> <comment> | generate ed25519 + load into agent/keychain + print the PUBLIC key | ⚠️ mutates |
Discovery (always run first)
scripts/ssh_config_audit.py # perms, Host blocks, Include, hardening, known_hosts
scripts/key_audit.py # key hygiene: types, perms, passphrases (metadata only)
scripts/agent_status.py # loaded identities vs keys on diskUnder the hood these run the read-only primitives below (nothing here reads a private key):
ls -la ~/.ssh # perms + inventory (dir should be 700)
ssh-add -l 2>/dev/null || echo "(agent empty / not running)" # loaded identities
for k in ~/.ssh/*.pub; do ssh-keygen -lf "$k"; done 2>/dev/null # key types/sizes (PUBLIC only)- Never
cata private key. Read type/size viassh-keygen -lf <key>.puband filenames only. ~/.ssh/configmay not exist yet → that's thesetuppath.
Core principles
- Verify, don't assume.
ssh -G <host>shows the effective resolved config;ssh -T git@github.comconfirms auth. Never call a change done without both. See reference/verification.md. - Private keys are secrets. Only ever surface a key's filename, type, and permissions — never
its contents. Public keys (
.pub) are safe to show and share. - Strict permissions or ssh refuses.
700 ~/.ssh,600private keys,644.pub. Loose perms make ssh silently ignore a key — fix perms before debugging auth. - Don't break working auth. Back up
~/.ssh/configbefore edits; test the new config resolves and authenticates before removing an old Host or key. - Prefer ed25519. Small, fast, modern. Flag
rsa< 3072 bits as weak.
Cross-skill coherence
- dotfiles (chezmoi): track
~/.ssh/configand~/.ssh/config.d/*and PUBLIC keys, but PRIVATE keys must be excluded (.chezmoiignore) or encrypted (chezmoi age) — never plaintext in git. See thedotfilesskill's secrets workflow; don't reimplement it here. - git-setup: SSH commit signing / auth reuses these keys — keep the identity consistent.
Settings
Read ~/.config/devenv/config.toml before prompting; if a [ssh-config] section exists, use it as
defaults (precedence: explicit answer this session > config.toml > ask). Had to ask? Offer to save
the answer back. Managed by the devenv skill. Keys honored:
key_type— preferred key algorithm for new keys (defaulted25519).
Safety
- NEVER print, commit, expose, or read a private key into the model's context. Only filenames,
types, permissions, and fingerprints leave this skill; the scripts derive everything from the
.puband from exit codes (grep -ql 'PRIVATE KEY',ssh-keygen -y … >/dev/null) — never the private bytes. Ops needing the key itself (generation, agent load) happen via the tooling, not by reading the material. Public keys (.pub) only. - Back up
~/.ssh/configbefore any edit (cp ~/.ssh/config ~/.ssh/config.bak). - Don't break working auth. Test the new config resolves (
ssh -G) and authenticates (ssh -T) before removing a Host or deleting a key. - Strict perms are mandatory — ssh rejects world/group-readable keys and configs. Fix perms rather than working around them.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

