Package Bash Completions with dh_bash-completion
You will add a Bash completion file to a Debian package, build it into the package's standard completion directory, and verify the resulting archive without changing the system Bash installation. Allow about fifteen minutes for a small package. You need a Debian package source tree, debhelper, and the bash-completion package available as a build dependency.
The route
Jump straight to the step you need, or tick off Done means at the end.
This guide describes the installed dh_bash-completion from bash-completion version 1:2.11-8. The local manual page is dated 18 September 2023. Package the files in your source tree first; installing the finished package on a machine is a separate, privileged operation.
1. Enable the debhelper addon
Add bash-completion to the source package's build dependencies. In a conventional Debian control file, the relevant part is:
Build-Depends: debhelper, bash-completion
Keep the debhelper compatibility level appropriate for your package. The important dependency here is bash-completion, because dh_bash-completion is provided by that package.
Next, make the debhelper sequence use the addon. If debian/rules already has a dh invocation, append the option rather than creating a second build path:
#!/usr/bin/make -f
%:
dh $@ --with bash-completion
The manual requires both parts: the build dependency and --with bash-completion. Without the addon, the helper is not part of the sequence even if its executable is installed.
Checkpoint
Confirm the dependency and option are present before editing completion files:
$ grep -E 'bash-completion|debhelper' debian/control
$ grep 'dh .*--with bash-completion' debian/rules
2. Choose the completion file format
The helper looks for a file named after the binary package, using this pattern:
debian/PACKAGE.bash-completion
Replace PACKAGE with the binary package name from the Package: field in debian/control, not necessarily the source package name. For a package called mytool, create debian/mytool.bash-completion.
There are two supported shapes. A proper Bash completion snippet is installed as one completion file, named after the binary package. For example:
_mytool_complete()
{
COMPREPLY=()
}
complete -F _mytool_complete mytool
This is a snippet, not a shell script that should be executed during package installation. It defines a completion function and registers it with Bash's complete builtin.
The other shape is a list of source files. Each non-empty, non-comment line names a file, optionally followed by the completion name to install:
src/mytool-completion
src/admin-completion mytool-admin
The first line is installed as mytool-completion, using the source file's basename. The second is installed under the explicit name mytool-admin. The source paths are resolved from the source directory, and the installed paths are placed below /usr/share/bash-completion/completions.
3. Keep the list unambiguous
Use the list format only when every referenced path exists at build time. A missing or mistyped path can make the installed helper fall back to treating the list file as a single completion snippet, which is not the result you intended. Comments and blank lines are allowed in a list, but keep each mapping on one line:
# Main command
src/mytool-completion
# Administrative subcommand
src/admin-completion mytool-admin
If you need one completion file only, the proper snippet format is less error-prone. Do not put prose comments that accidentally resemble shell syntax in a snippet unless they are valid Bash comments.
Checkpoint
Verify the package name and all list paths without changing anything:
$ dpkg-parsechangelog -S Source
$ sed -n '/^Package:/p' debian/control
$ test -f debian/mytool.bash-completion
$ test -f src/mytool-completion
4. Build the package
Run your normal Debian package build from the source root. For a local test build, this commonly looks like:
$ dpkg-buildpackage -us -uc
The flags avoid signing the test source and binary packages. They do not install anything. Let the build finish before inspecting the output; a completion file is part of the package payload, not a file copied into /usr/share on the build host.
If the build fails because the build dependency is unavailable, install or otherwise provide the declared build dependencies through your normal packaging environment. Do not work around the missing dependency by copying dh_bash-completion into the source tree.
5. Verify the archive contents
Inspect the generated binary package with dpkg-deb. Replace the placeholder archive with the exact file produced by your build:
$ dpkg-deb -c ../mytool_1.0-1_amd64.deb | grep 'usr/share/bash-completion/completions/'
-rw-r--r-- root/root 123 2026-09-23 02:30 ./usr/share/bash-completion/completions/mytool-completion
The timestamp and size will differ. The useful check is the path and filename. For the proper snippet format, expect the binary package name as the installed completion filename. For the list format, expect the basename or explicit name selected on each line.
You can inspect the file content without installing the package:
$ dpkg-deb --fsys-tarfile ../mytool_1.0-1_amd64.deb \
| tar -xOf - ./usr/share/bash-completion/completions/mytool-completion
_mytool_complete()
{
COMPREPLY=()
}
This is a read-only archive check. It does not require sudo. Installing the package later may require root privileges and will change the target machine's filesystem, so perform that separately after reviewing the package.
6. Recover from a wrong completion
If the archive contains the wrong name or content, do not repair /usr/share/bash-completion by hand. Correct debian/PACKAGE.bash-completion or the referenced source file, remove only the affected build output if your build workflow requires a clean rebuild, and build again.
If you already installed a bad package, rebuild a corrected package and upgrade it through your normal package-management process. To remove that package, use your normal Debian package removal command, but keep in mind that removal also removes the packaged completion file and may affect users who rely on it. The source tree remains the place to make the durable fix.
A successful package build proves that the file was packaged. It does not prove that a completion function behaves correctly for every command-line case. Test the completion snippet in a disposable shell or package test environment after checking the archive.
Done means
bash-completionis declared as a build dependency.debian/rulespasses--with bash-completiontodh.- The file name matches the binary package name.
- The snippet or file list uses the format intended for this package.
dpkg-deb -cshows the expected file below/usr/share/bash-completion/completions.- No system completion directory was edited during the build.