Bash completion for Hugo does not just appear: you generate a script, load it, and decide whether it should survive a reboot. You will generate Hugo's Bash completion, load it into the shell you are using now, and optionally install it so new Bash sessions load it automatically. The examples match Hugo 0.123.7, the version installed on the machine used for this guide.
Allow about ten minutes. You need Hugo, Bash, and the bash-completion package. The generation and temporary-shell tests are ordinary user commands. Writing the system-wide file under /etc requires elevated privileges.
Check the executable, Hugo version, and completion package before changing anything. These commands only read local state:
$ command -v hugo
/usr/bin/hugo
$ hugo version
hugo v0.123.7+extended linux/amd64 BuildDate=2026-03-17T19:51:14Z VendorInfo=ubuntu:0.123.7-1ubuntu0.3+esm2
$ dpkg-query -W -f='${Package} ${Version}\n' bash-completion
bash-completion 1:2.11-8
Your build date and package revision may differ. The important checks are that hugo resolves to the program you expect and that Bash completion is installed. If command -v prints nothing, fix your PATH or install Hugo through your normal package-management process, rather than generating a file from a different Hugo binary by accident.
Checkpoint: continue only when hugo version succeeds and the completion package is present.
Ask the installed program for the command's help. This confirms the local interface and shows the two options specific to Bash completion:
$ hugo completion bash --help
Generate the autocompletion script for the bash shell.
This script depends on the 'bash-completion' package.
...
Flags:
-h, --help help for bash
--no-descriptions disable completion descriptions
The output is longer than the excerpt above. --no-descriptions removes descriptions from completion results; leave it out unless you want a smaller or less descriptive script. The command is hugo completion bash, not the separate hugo completion parent command.
Hugo writes the generated shell code to standard output. It does not install a package, edit your shell startup files, or alter a Hugo site by itself.
Use process substitution to generate and source the script in the current Bash process:
$ source <(hugo completion bash)
This is temporary: it changes completion functions in the current interactive shell but does not persist after that shell exits. It also relies on Bash process substitution, so do not paste it into a shell that is not Bash.
Test a Hugo subcommand by typing the prefix and pressing Tab. For a non-interactive check that does not depend on your terminal, inspect the generated output instead:
$ hugo completion bash | grep -m1 '__start_hugo'
__start_hugo()
If sourcing reports that bash-completion is missing, install that package using your distribution's documented method, then open a new Bash shell and repeat the step. A completion script can be generated without completion support being loaded, but the interactive result may not work correctly.
A user-local file avoids sudo and is easier to undo. Create the directory if necessary, then write a temporary file before replacing the final file:
$ mkdir -p "$HOME/.local/share/bash-completion/completions"
$ tmp=$(mktemp "$HOME/.local/share/bash-completion/completions/hugo.XXXXXX")
$ hugo completion bash > "$tmp"
$ test -s "$tmp" && mv -- "$tmp" "$HOME/.local/share/bash-completion/completions/hugo"
$ wc -c "$HOME/.local/share/bash-completion/completions/hugo"
11657 /home/you/.local/share/bash-completion/completions/hugo
The byte count is an example from Hugo 0.123.7 and can change with the Hugo build. The temporary name prevents a failed generation from truncating the existing completion file: if the command fails, inspect the temporary file and remove it only after confirming it is disposable. The existing final file is left in place.
This location is the conventional user completion directory used by Bash completion installations, but a distribution can configure a different search path. Check the active paths before relying on it:
$ bash -ic 'printf "completion directories:\n%s\n" "${BASH_COMPLETION_USER_DIR:-$HOME/.local/share/bash-completion}"' 2>/dev/null
completion directories:
/home/you/.local/share/bash-completion
If your system's Bash completion setup does not search that directory, source the file from your Bash startup file instead. Add this line to ~/.bashrc only if it is not already present:
source "$HOME/.local/share/bash-completion/completions/hugo"
Open a new Bash shell, or source the file in the current one:
$ source "$HOME/.local/share/bash-completion/completions/hugo"
$ type __start_hugo
__start_hugo is a function
Recovery: to undo the user-local setup, first remove the source line from ~/.bashrc if you added it, then remove the generated completion file. This removes only the completion definition, not Hugo or any site data. In a shell that already loaded it, start a new shell to clear the old function.
Use the system-wide path only when every user on the machine needs Hugo completion. This writes under /etc and requires elevated privileges.
Warning: the final path may already contain a completion script maintained by your package manager. Inspect it before replacing it, and keep a backup if it is present.
$ sudo test -e /etc/bash_completion.d/hugo && sudo cp --preserve=all /etc/bash_completion.d/hugo /etc/bash_completion.d/hugo.backup
$ sudo hugo completion bash > /tmp/hugo-completion.bash
$ test -s /tmp/hugo-completion.bash
$ sudo install -o root -g root -m 0644 /tmp/hugo-completion.bash /etc/bash_completion.d/hugo
The redirection to /tmp happens as your user, so Hugo's errors remain visible and no partial root-owned file is created. install replaces the destination only after the generated file has passed the non-empty check. Starting a new Bash shell is the least surprising way to load the system file:
$ bash -ic 'type __start_hugo'
__start_hugo is a function
Recovery: to recover the previous system file, use the backup you made:
$ sudo install -o root -g root -m 0644 /etc/bash_completion.d/hugo.backup /etc/bash_completion.d/hugo
If no backup existed, regenerate the file with the Hugo version your package supplies. Do not delete a package-managed file casually: a future package upgrade may restore or modify it.
If pressing Tab does nothing, verify that you are in Bash, that the completion package is loaded, and that the function exists:
$ printf '%s\n' "$BASH_VERSION"
5.2.21(1)-release
$ type _init_completion
_init_completion is a function
$ type __start_hugo
__start_hugo is a function
An absent _init_completion usually means the Bash completion framework has not been loaded. An absent __start_hugo means the Hugo script was not sourced, or another startup file reset the shell state. Run the explicit source command from step 3 to separate a loading problem from a startup-file problem.
If completion lists are stale after upgrading Hugo, regenerate the file with the new binary and start a new shell. The generated script is versioned output, not a live query of Hugo, so keep the generation command in your setup notes and refresh it deliberately after package upgrades.
hugo version identifies the intended installed Hugo binary, and the bash-completion package is present.hugo completion bash produces a non-empty script.