Shell completion is the feature that finishes what you are typing when you press the Tab key. In its simplest form the shell completes filenames and directory paths from the current working directory, and command names from the directories on your PATH. Type a few letters and a Tab, and the shell either fills in the unique match or, if several match, shows the candidates. This started as a convenience for the two things shells deal with constantly, files and commands, and it dramatically reduces typing and typos at the command line.
Programmable completion extends this so the shell can complete a command’s own arguments, not just paths. The Bash manual explains that when a user attempts completion for a command “for which a completion specification (a compspec) has been defined using the complete builtin, Readline invokes the programmable completion facilities” (https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html). A completion function is an ordinary shell function bound to a command; the shell passes it the command name, the word being completed, and the preceding word, and the function returns the appropriate candidates. This lets, for example, a git completion offer branch names after “git checkout”, or a package manager offer installed package names after its remove subcommand.
In practice most of these completion functions are not written by individual users but shipped by the bash-completion project, which the project describes as a collection providing “programmable completion functions for bash” along with helpers for writing and loading new ones (https://github.com/scop/bash-completion). Installing it gives hundreds of commands rich, argument-aware Tab completion out of the box, sourced automatically when an interactive shell starts. This is why on a well-configured system pressing Tab after a tool name often surfaces exactly that tool’s flags and subcommands.
The Z shell took a more ambitious approach with its completion system, known as compsys. The zsh documentation describes a system of shell functions, initialized by autoloading and running compinit, that is “contextual, sensitive to the point at which completion is started” and configured through styles and tags rather than ad hoc functions (https://zsh.sourceforge.io/Doc/Release/Completion-System.html). Styles let a user tune how completions are generated and displayed, while tags classify what is being completed, giving zsh a reputation for the most powerful and customizable completion of any common shell.
For day-to-day work, shell completion is one of the highest-leverage usability features a command line offers. It turns the shell from something you must memorize into something that discloses its options as you type, lowering the cost of using unfamiliar tools and reducing errors on familiar ones. The completion definitions themselves are just shell code, often loaded from dotfiles or a system directory, which keeps the feature open, inspectable, and extensible in the same spirit as the rest of the Unix environment.