I have created a .zsh script that will prompt the user a ssh key just for GitHub when running git clone or git push. All the other git commands remain the same. You can even pass the standard flags with no issue and select the key with the keyboard arrows.
git_sshprompt.zsh
#!/bin/zsh
# Colors for the terminal output
COLOR_RESET="\033[0m"
COLOR_GREEN="\033[32m"
COLOR_YELLOW="\033[33m"
COLOR_CYAN="\033[36m"
COLOR_BLUE="\033[34m"
COLOR_RED="\033[31m"
COLOR_BOLD="\033[1m"
# Emojis for enhanced user experience
EMOJI_GITHUB="🍏"
EMOJI_SELECT="🔑"
EMOJI_ERROR="❌"
EMOJI_SUCCESS="✅"
EMOJI_ARROW="➡️" # Right arrow emoji
# Path to the SSH config file
SSH_CONFIG="$HOME/.ssh/config"
declare -A SSH_KEYS
index=1
if [[ ! -f $SSH_CONFIG ]]; then
echo -e "${EMOJI_ERROR} ${COLOR_RED}${COLOR_BOLD}SSH config file not found at $SSH_CONFIG.${COLOR_RESET}"
exit 1
fi
# Initialize variables
is_github=false
# List all available IdentityFile keys for HostName github.com
echo -e "${EMOJI_GITHUB} ${COLOR_CYAN}${COLOR_BOLD}Available SSH identities for github.com:${COLOR_RESET}"
while read -r line; do
# Check for Host github.com
if [[ $line =~ ^Host\ github\.com ]]; then
is_github=true
elif [[ $is_github == true && $line =~ ^IdentityFile ]]; then
key_path=${line#IdentityFile }
SSH_KEYS[$index]=$key_path
echo -e " ${COLOR_YELLOW}${COLOR_BOLD}[$index]${COLOR_RESET} $key_path"
((index++))
elif [[ $is_github == true && -z $line ]]; then
# Stop collecting when we reach an empty line or another Host block
is_github=false
fi
done < $SSH_CONFIG
if [[ ${#SSH_KEYS[@]} -eq 0 ]]; then
echo -e "${EMOJI_ERROR} ${COLOR_RED}${COLOR_BOLD}No IdentityFile entries found for github.com in $SSH_CONFIG.${COLOR_RESET}"
exit 1
fi
# Check if the Git command is 'git push' or 'git clone'
if [[ "$1" == "push" ]]; then
# For git push, no repository URL is needed
echo -e "${EMOJI_ARROW} ${COLOR_BOLD}Select an SSH identity for git push:"
elif [[ "$1" == "clone" && -z "$2" ]]; then
# If git clone is called but no URL is provided
echo -e "${EMOJI_ERROR} ${COLOR_RED}${COLOR_BOLD}No repository URL provided for git clone. Exiting.${COLOR_RESET}"
exit 1
elif [[ "$1" == "clone" && -n "$2" ]]; then
# If git clone is called and a URL is provided
echo -e "${EMOJI_ARROW} ${COLOR_BOLD}Select an SSH identity for git clone:"
else
# For other commands (git pull, git fetch, etc.), skip the prompt
command git "$@"
exit 0
fi
# Use fzf for selecting the SSH key, but stay in the same window
selected_key=$(printf "%s\n" "${(@)SSH_KEYS[@]}" | fzf --height 20 --border --ansi \
--prompt="${EMOJI_ARROW} Select an SSH identity: " --preview "echo {}")
if [[ -z $selected_key ]]; then
echo -e "${EMOJI_ERROR} ${COLOR_RED}${COLOR_BOLD}No SSH key selected. Exiting.${COLOR_RESET}"
exit 1
fi
# Display the selected SSH key
echo -e "${EMOJI_SUCCESS} ${COLOR_GREEN}${COLOR_BOLD}You selected SSH key:${COLOR_RESET} $selected_key"
# Check if repository URL is provided (only for git clone)
if [[ "$1" == "clone" && -n "$2" ]]; then
repo_url=$2
# Check for additional flags or arguments and pass them along with the git command
shift 2 # Remove 'clone' and the URL from the arguments
echo -e "${EMOJI_ARROW} ${COLOR_BOLD}Cloning repository: $repo_url${COLOR_RESET}"
GIT_SSH_COMMAND="ssh -i $selected_key" git clone "$repo_url" "$@"
elif [[ "$1" == "push" ]]; then
# For git push, no URL is required, so just set the SSH key and push with any flags
shift 1 # Remove 'push' from the arguments
echo -e "${EMOJI_ARROW} ${COLOR_BOLD}Pushing changes to the remote repository${COLOR_RESET}"
GIT_SSH_COMMAND="ssh -i $selected_key" git push "$@"
fi
.zshrc
git_with_key() {
# Check if the command is 'git clone' or 'git push'
if [[ "$1" == "clone" || "$1" == "push" ]]; then
# Call the script to prompt for SSH key selection, passing all arguments
$ZSH_CUSTOM/plugins/gitssh/git_sshprompt.zsh "${(@)argv}"
else
# Otherwise, run the regular git command
command git "$@"
fi
}
# Make sure to replace the regular git command with the git_with_key function
alias git="git_with_key"
git clone example

git push example
