SSH Config Summary
{{ hosts.length }} {{ hosts.length===1 ? 'host' : 'hosts' }}
Grouped: {{ groupingLabel }}
Groups {{ groupedHosts.length }} Known keys {{ knownKeys.length }} Wildcards {{ wildcardHostCount }} {{ lintResults.length }} warning(s) Alerts {{ securityCounts.total }}

          
Drop a file or paste SSH config to begin.
Search:
Host blocks
No hosts loaded yet. Paste a config above or click “Add host” to start fresh.
No hosts match the current filter.
Drag-and-drop ordering is available when alphabetical sorting is off and no search filter is applied.
{{ item.title }}
Key Value Actions
No directives yet. Use “Add line”.
{{ matchCount }} match(es):
Host Domain Keys Wildcard Copy
{{ r.host }} {{ r.domain || '—' }} {{ r.keyCount }} {{ r.wild ? 'Yes' : 'No' }}
No rows

        
HostIssueCopy
{{ w.host }} {{ w.issue }}
No issues found.
No security concerns detected with the current configuration.
Severity Host Issue Recommendation Copy
{{ finding.severityLabel }} {{ finding.host || 'Global' }} {{ finding.issue }} {{ finding.recommendation }}
Directive insights will appear once hosts and directives are loaded.
Directive Hosts Unique values Missing Example value Copy
{{ row.key }} {{ row.hostCount }} {{ row.uniqueValues }} {{ row.missingHosts }} {{ row.sampleValue || '—' }}
Load a baseline configuration to compare changes.
No changes detected against the imported baseline.
{{ line.marker }} {{ line.text }}
Note: This tool cannot directly save to ~/.ssh/config. Download and replace it manually when done.
:

Introduction:

SSH client configuration is the layer that turns a short alias into a real connection plan. A single Host block can decide which server name to reach, which account to use, which key to offer, whether a jump host is involved, and whether local or remote ports should be forwarded. When that file grows over time, the hardest part is often not typing the directives. It is seeing which host blocks are clear, which ones drifted, and which settings quietly widen trust.

This editor is built for that review pass. You can drop or paste a config, split it into editable host blocks, search across patterns and values, group entries by wildcard usage or domain suffix, reorder them, and rebuild a cleaner version for copy or download. The same session also exposes a JSON view, a structural lint table, a security review table, a directive insights table, and a diff against the imported baseline.

That combination is useful because SSH mistakes are often subtle rather than dramatic. A broad wildcard such as db-*, a permissive StrictHostKeyChecking setting, agent forwarding, or a forwarded port bound to 0.0.0.0 can sit in a config for months before anyone stops to review it. A long file can still be valid enough to work while being hard to audit safely.

Everything the editor does stays in the browser session. Parsing, matching, preview generation, diffing, JSON export, CSV export, and DOCX export all happen locally in the page. You still replace your real ~/.ssh/config yourself, and the editor does not verify remote host keys, test whether files exist on disk, or log into any server.

The most important limit is that this is a config review surface, not a full OpenSSH evaluator. It does not expand included files, does not execute Match conditions, does not merge global defaults from Host * into later stanzas, and does not preserve comments and non-host lines in their exact original positions. If your workflow depends heavily on inheritance, conditional logic, or layered includes, treat the rebuilt file as a draft that still needs a deliberate SSH-aware check.

Technical Details:

The editor reads the imported text as a series of visible Host stanzas. Inside each stanza it stores directive rows, accepts both known SSH client keys and custom keys, and rebuilds the output from that structured view. Leading comments plus non-host lines such as Include and Match can be retained as top-level text when you enable preservation, but the editor does not execute them and does not keep them anchored to their original locations inside the file.

How the editor treats a config file
Paste or drop text split visible Host blocks into editable rows optionally preserve top-level comments, Include, and Match lines as shared non-host text apply optional sorting, key normalization, de-duplication, and header comment generate preview, JSON, lint, security findings, directive insights, and diff output

The cleanup controls are deterministic, which makes them predictable but also means they can change meaning if you use them carelessly. OpenSSH normally uses the first obtained value for most parameters, while this editor's optional de-duplication keeps the last repeated key inside a host block. That is an editing choice, not an attempt to reproduce final SSH resolution. It matters most when repeated directives are intentional.

Cleanup options in the SSH client config editor
Option What it changes Why to review it carefully
Sort hosts alphabetically Reorders host stanzas by host pattern in the rebuilt file. Safe for readability, but it can hide the original authoring order you may want when comparing changes.
Sort keys within each host Applies the editor's fixed directive order before rendering each host block. Good for cleanup, but it rearranges the file and makes the diff broader.
Normalize key case Converts known directive names to canonical SSH-style casing such as HostName and StrictHostKeyChecking. Useful for consistency, but cosmetic changes can make a quick diff look larger than the functional change really is.
De-duplicate repeated keys Keeps the last repeated directive name inside the same host block. Potentially risky because repeated keys can be intentional for directives such as IdentityFile, LocalForward, or RemoteForward.
Preserve non-Host lines Prepends stored non-host lines before the rebuilt host blocks. Retention is useful, but the original placement and conditional context are not preserved.
Include header comment Adds a generated comment line at the top of the output. Helpful for handoff, but it changes the file even if no host logic changed.

The Match tester is intentionally lightweight. It compares the sample hostname against whitespace-separated Host patterns, supports * and ?, and matches without regard to letter case. It is useful for quick sanity checks on aliases and wildcards, but it is not a full simulation of OpenSSH pattern logic. Negated patterns, inherited defaults, and conditional Match criteria are outside its model.

Grouping is also a convenience view rather than SSH resolution. Wildcard grouping simply separates patterns that contain * or ?. Domain grouping pulls the suffix from the first visible host token after its first dot. That makes it easy to scan a fleet, but it is not DNS-aware and does not reflect hostname canonicalization.

Built-in analysis surfaces in the SSH client config editor
Surface What it checks What it does not prove
Lint Empty host patterns, hosts with no directives, repeated keys, and empty directive values. A repeated key warning does not automatically mean the SSH config is invalid, because some directives may intentionally appear more than once.
Security Root login, missing or relaxed host-key checks, missing IdentityFile, password authentication, agent forwarding, wide local or remote binds, ControlMaster without ControlPersist, missing HostName, and UpdateHostKeys no. A quiet table does not guarantee the effective SSH session is safe when your real config depends on inherited defaults, includes, or conditional logic.
Insights How many hosts use each directive, how many distinct values appear, how many hosts are missing it, and one sample value. It shows coverage and drift, not whether a directive is appropriate for every host.
Diff Line-by-line changes between the imported baseline and the rebuilt output. It confirms what changed in text form, not what OpenSSH would ultimately apply after all matching rules are processed.

For smaller files the diff view uses a more contextual comparison, while very large comparisons fall back to a simpler line-by-line pass so the page stays responsive. The JSON export collects the visible host blocks, line details, wildcard flags, non-host text, and current cleanup options. The Hosts, Security, and Insights tabs also support CSV or DOCX export so you can hand a review summary to someone who does not need the raw config itself.

Everyday Use & Decision Guide:

The best way to use the editor is as a controlled rewrite of text you already have. Import the real config first, even if you expect to clean most of it up, because that gives the diff view a true baseline and lets the summary box reflect the file you actually maintain.

Once the file is loaded, decide whether you are dealing with independent host stanzas or with layered SSH logic. If each host block is fairly self-contained, the editor can be a strong cleanup aid. If the file relies on Host * defaults, nested includes, or conditional Match rules, the editor is still useful for inspection, but the result needs more manual judgment because the final runtime config may inherit behavior that the page never models.

Search and grouping are the safest first moves. They help you spot families of hosts before you change anything. A wildcard-heavy file often benefits from grouping by wildcard first, because broad patterns deserve more scrutiny than literal one-off aliases. Domain grouping is helpful when you maintain separate environments such as production, staging, and internal service networks.

Use cleanup switches one at a time. Sorting and key normalization are usually low-risk readability changes. De-duplication deserves a slower review because repeated lines are not always mistakes in SSH. Multiple IdentityFile entries can be intentional, and multiple forwarding rules are a normal part of some workflows. In this editor, repeated keys are treated as something to review structurally, not as a promise that OpenSSH would reject them.

The security view is strongest when it helps you rank what to read next. A high-severity row means a setting deserves an explicit decision. It does not mean every use is impossible. The same is true in reverse. No findings means the visible rows did not trigger the editor's built-in rules. It does not mean the remote host is trusted, that included files are clean, or that inherited defaults are harmless.

Finish every serious edit in the preview and the diff. The preview shows the exact text you are about to copy or download. The diff shows whether the rebuilt file changed only where you intended. If those two views still look larger or stranger than expected, stop there and review before replacing your real SSH config.

Step-by-Step Guide:

  1. Drop your current SSH client config onto the preview area or paste it while the preview is focused. Starting from the real file gives the diff view something meaningful to compare.
  2. Use search, wildcard grouping, or domain grouping to find the host blocks you actually care about before you change formatting.
  3. Open the relevant host panels and edit the visible directives. Use built-in directive names when they fit, and switch to a custom key when your config needs something outside the editor's known list.
  4. Turn on cleanup options gradually. Apply sorting or case normalization first. Only use de-duplication after you confirm repeated directives are not intentional in that block.
  5. Read the Lint, Security, and Insights tabs together. Structural warnings tell you where the text is messy. Security findings tell you where trust deserves a closer look. Insights show where values drift across hosts.
  6. Review the rebuilt preview and the Diff tab, then use copy or download to export the result. Replace your actual SSH config manually when you are satisfied, because the editor does not write to ~/.ssh/config directly.

Interpreting Results:

The summary box is a fast triage layer, not a full audit. Host count tells you how many visible Host stanzas were parsed. Wildcard count tells you how much pattern-based matching is in play. Warning and alert badges tell you where to start reading next. The Known keys badge is the size of the editor's built-in directive catalog, not a count of how many directive types your imported file uses.

The Hosts tab is the best quick inventory view. It shows each host pattern, a rough domain label, the number of directives that survive the current output options, and whether the pattern contains wildcards. The copy action on that table is useful when you want to share one host block for review without sharing the entire config.

The JSON tab is a structured snapshot of what the page currently sees. It is useful when you want to archive the review state, inspect host rows programmatically, or compare how option toggles change the reconstructed model. Because it mirrors the editor's internal view, it also reflects the editor's limits. It is not the same thing as OpenSSH's fully evaluated runtime result.

  • Lint is best read as structural review. Clear empty keys and empty values early, then judge duplicate-key warnings with SSH semantics in mind.
  • Security is best read as review priority. A finding means the visible setting deserves intent and context, not blind removal.
  • Insights is best read as a drift map. High unique-value counts or many missing hosts often show where configuration sprawl has crept in.
  • Diff is the final check before export. If the diff is broader than expected, your cleanup options probably changed more than you intended.

Worked Examples:

A compact deployment alias. Say your file contains Host web-prod, HostName web01.internal, User deploy, IdentityFile ~/.ssh/id_ed25519, and StrictHostKeyChecking yes. The editor will show one host, no wildcard, and usually no security findings. In that case the page is acting as a clean confirmation that the visible alias is explicit and easy to copy into a new workstation or teammate setup.

A wildcard that needs a deliberate trust decision. Now picture Host db-* with User root, StrictHostKeyChecking accept-new, ForwardAgent yes, and LocalForward 0.0.0.0:5432 db.internal:5432. The editor will surface that block quickly because the wildcard count goes up and the security table reports several concerns. The point is not that the block can never be justified. The point is that one permissive profile now applies broadly, so the file deserves review before that pattern spreads further.

A config that relies on shared defaults. Imagine a real file that starts with Host * carrying your standard IdentityFile and UpdateHostKeys yes, followed by narrow host aliases that only override HostName and User. OpenSSH can apply those defaults across matching hosts, but the editor evaluates each visible stanza on its own. A later host block may therefore look as if it lacks an identity file even though the live SSH client would inherit one. In that situation the warning is still useful as a reminder to inspect the structure, but it is not a final statement about runtime behavior.

A repeated key that is not automatically a mistake. Suppose a bastion entry has two LocalForward lines and two IdentityFile lines because you use multiple tunnels and fallback identities. The lint view marks repeated keys, and the de-duplication switch would keep only the last line for each repeated directive. That makes the page helpful for spotting complexity, but it also means you should avoid using de-duplication as a blanket cleanup button on multi-forward or multi-key host blocks.

FAQ:

Does the editor upload my SSH config anywhere?

No. The page has no server-side handler for parsing or export. Import, analysis, diffing, and file generation stay in the browser session.

Does it understand Host *, Include, and Match the same way OpenSSH does?

No. It can preserve visible non-host lines and it can count simple host-pattern matches, but it does not fully evaluate inherited defaults, conditional matching, or included files. Treat those parts of your config as context the editor helps you review, not logic it fully simulates.

Why does the page warn about duplicate keys when SSH sometimes allows repeated directives?

The lint pass is conservative. It flags repeated directive names as something to review structurally. OpenSSH does allow multiple entries for some settings, including multiple identity files and multiple forwarding lines, so a duplicate warning is not automatically an error.

Why can the de-duplication option change meaning?

Because the editor keeps the last repeated key inside a host block when de-duplication is enabled. OpenSSH itself generally uses the first obtained value for most parameters, and some directives are intentionally repeatable. Review those hosts manually before using the switch.

Does a clean security table mean the host setup is safe?

No. It only means the visible directives did not trigger the editor's built-in checks. It does not verify host fingerprints, confirm remote policy, validate file paths, or evaluate included and inherited configuration.

Can I keep directives that are not in the built-in dropdown list?

Yes. The editor supports custom directive names, so it can still rebuild host blocks that use less common SSH client options.

Glossary:

Host
A pattern that selects which later directives should apply to matching destination names.
HostName
The real server name or address that an alias should connect to.
IdentityFile
A private-key path that SSH may offer during public-key authentication.
StrictHostKeyChecking
The setting that controls how the client treats new or changed host keys in known-hosts checks.
ProxyJump
A jump-host setting that routes the connection through one or more intermediate SSH hosts.
LocalForward and RemoteForward
Port-forwarding rules that expose a listening socket on the client side or the server side and tunnel traffic through SSH.

References:

  • ssh_config(5), OpenBSD manual pages. Used for host-pattern precedence, Host and Match behavior, repeated IdentityFile entries, forwarding semantics, and host-key checking rules.
  • ssh(1), OpenBSD manual pages. Used for agent-forwarding caution, jump-host context, and how wildcard binds affect forwarded ports.