selector[str_String] :=
GroupBy[list, EditDistance[str, #] <= 2 &][True] /.
str -> Style[str, Red, Bold]
list = {"horse", "horses", "morse", "morses", "norse", "norses",
"fox", "monses", "goose", "tool", "goal", "tools", "gothe"};
selector /@ list
Alternatively,
selector2[str_String] :=
Thread[str -> GroupBy[list, 0 < EditDistance[str, #] <= 2 &][True]]
Flatten[selector2 /@ list] /. Missing[__] :> {}
(* {"horse" -> "horses", "horse" -> "morse", "horse" -> "morses",
"horse" -> "norse", "horse" -> "norses", "horse" -> "goose",
"horses" -> "horse", "horses" -> "morse", "horses" -> "morses",
"horses" -> "norse", "horses" -> "norses", "horses" -> "monses",
"morse" -> "horse", "morse" -> "horses", "morse" -> "morses",
"morse" -> "norse", "morse" -> "norses", "morse" -> "monses",
"morse" -> "goose", "morses" -> "horse", "morses" -> "horses",
"morses" -> "morse", "morses" -> "norse", "morses" -> "norses",
"morses" -> "monses", "norse" -> "horse", "norse" -> "horses",
"norse" -> "morse", "norse" -> "morses", "norse" -> "norses",
"norse" -> "goose", "norses" -> "horse", "norses" -> "horses",
"norses" -> "morse", "norses" -> "morses", "norses" -> "norse",
"norses" -> "monses", "fox" -> {}, "monses" -> "horses", "monses" -> "morse",
"monses" -> "morses", "monses" -> "norses", "goose" -> "horse",
"goose" -> "morse", "goose" -> "norse", "goose" -> "gothe", "tool" -> "goal",
"tool" -> "tools", "goal" -> "tool", "tools" -> "tool", "gothe" -> "goose"} *)
Select[Tuples[words, 2], EditDistance[#[[1]], #[[2]]] <= 2 &]
$\endgroup$