Skip to content

Instantly share code, notes, and snippets.

@backerman
Last active March 4, 2025 22:45
Show Gist options
  • Save backerman/2c91d31d7a805460f93fe10bdfa0ffb0 to your computer and use it in GitHub Desktop.
Save backerman/2c91d31d7a805460f93fe10bdfa0ffb0 to your computer and use it in GitHub Desktop.
Enable tab completion for ssh hostnames in PowerShell
using namespace System.Management.Automation
Register-ArgumentCompleter -CommandName ssh,scp,sftp -Native -ScriptBlock {
param($wordToComplete, $commandAst, $cursorPosition)
$knownHosts = Get-Content ${Env:HOMEPATH}\.ssh\known_hosts `
| ForEach-Object { ([string]$_).Split(' ')[0] } `
| ForEach-Object { $_.Split(',') } `
| Sort-Object -Unique
# For now just assume it's a hostname.
$textToComplete = $wordToComplete
$generateCompletionText = {
param($x)
$x
}
if ($wordToComplete -match "^(?<user>[-\w/\\]+)@(?<host>[-.\w]+)$") {
$textToComplete = $Matches["host"]
$generateCompletionText = {
param($hostname)
$Matches["user"] + "@" + $hostname
}
}
$knownHosts `
| Where-Object { $_ -like "${textToComplete}*" } `
| ForEach-Object { [CompletionResult]::new((&$generateCompletionText($_)), $_, [CompletionResultType]::ParameterValue, $_) }
}
@hpawe01
Copy link

hpawe01 commented Nov 20, 2024

If you want to simplify the script and just want to use the host-aliases without the user@ part in your ssh command, you can use the following script:

using namespace System.Management.Automation

$script = {
  param($wordToComplete)    

  Get-Content ${Env:HOMEPATH}\.ssh\config `
    | Select-String -Pattern "^Host " `
    | ForEach-Object { $_ -replace "host ", "" -split " " } `
    | Sort-Object -Unique `
    | Where-Object { $_ -like "$wordToComplete*" } `
    | ForEach-Object { "$_" }
}

Register-ArgumentCompleter -CommandName ssh,scp,sftp -ScriptBlock $script

This autocompletes for example ssh du⭾ to ssh dummy which will internally calls ssh [email protected], given the following ~\.ssh\config:

Host dummy
  Hostname dummy.com
  User admin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment