3 min read

On Enabling Bash Completion for Aliases

Bash completion is pretty sweet. Unfortunately, one can’t get that same sweetness when creating an alias.

Why, and what to do about it?

To demonstrate the problem, I added an alias for kubectl simply called k:

$ alias k
alias k='kubectl'

I then immediately tried to use it, convinced of my command-line efficiency and cleverness:

$ k [TAB] [TAB]
cm/         deployment/ po/         pv/         pvc/        rs/         svc/

Um, say what? Why did it list the contents of the current working directory and not the kubectl subcommands (by the way, this is the default behavior)?

It’s because the Bash complete builtin isn’t aware of the alias!

So, why does the completion work for the kubectl command? Because the complete program is aware of the kubectl command!

$ complete | ag kubectl
complete -o default -F __start_kubectl kubectl

Now that we know what needs to be done, let’s register the k alias with complete, referencing the same Bash function as the kubectl function!

$ complete -F __start_kubectl k
$ complete | ag kubectl
complete -F __start_kubectl k
complete -o default -F __start_kubectl kubectl

As you can see above, complete is now aware of the k alias!

Let’s see what happens now with tab completion:

$ k [TAB] [TAB]
annotate       attach         cluster-info   cp             describe       exec           help           options        proxy          scale          uncordon
api-resources  auth           completion     create         diff           explain        kustomize      patch          replace        set            version
api-versions   autoscale      config         debug          drain          expose         label          plugin         rollout        taint          wait
apply          certificate    cordon         delete         edit           get            logs           port-forward   run            top

And now it works! Weeeeeeeeeeeeeeeeeeeeeeeeeeee!!!

So, this is great, but it was really bothering me that the provenance of the __start_kubectl function wasn’t readily apparent. Where did it come from?

This wasn’t the easiest question to answer, because it turns out that this is an auto-generated function that isn’t even from the kubectl project’s source code.

You can see the __start_kubectl function when viewing the generated full completion file and grepping:

$ kubectl completion bash | ag "__start_kubectl"
    complete -o default -F __start_kubectl kubectl
    complete -o default -o nospace -F __start_kubectl kubectl

And here is its function definition:

$ declare -f __start_kubectl
__start_kubectl ()
    local cur prev words cword;
    declare -A flaghash 2> /dev/null || :;
    declare -A aliashash 2> /dev/null || :;
    if declare -F _init_completion > /dev/null 2>&1; then
        _init_completion -s || return;
        __kubectl_init_completion -n "=" || return;
    local c=0;
    local flags=();
    local two_word_flags=();
    local local_nonpersistent_flags=();
    local flags_with_completion=();
    local flags_completion=();
    local commands=("kubectl");
    local must_have_one_flag=();
    local must_have_one_noun=();
    local has_completion_function;
    local last_command;
    local nouns=();

However, there’s nothing in the kubectl project’s source code that matches that text or looks like it could have generated it.

Yet still I pressed on, continuing the search like Sherlock fucking Holmes.

I next thought to check out the cobra Golang project, which tons of Golang projects use. And…that’s a bingo!

To understand the birthplace of the __start_kubectl function, check out the GenBashCompletion method in the cobra project’s source code to see how the __start_kubectl Bash function is auto-generated and appended to the file that is sourced to enable Bash completion in kubectl.

Sometimes, as seen here, the project is nice and provides the hooks needed to install Bash completion of their assets. Let’s look give a big hurrah to all the kind contributors at the kubernetes project who have given us the tools to get all nice and setup in our own little dev environment.


There is a lot more to the Bash builtins that assist with Bash completion than what I’ve presented here. My goal was to do a quick post on a specific matter, and so it goes.

Also, what’s up with all the exclamation points!