That’s when I knew the air-gapped deployment hadn’t gone all the way. Shell completion is not just a convenience; in isolated environments, it’s a necessity for speed, accuracy, and sanity. When a system is cut off from the internet, every tool you install travels through a careful pipeline: download in a trusted zone, transfer via secure media, load into the target, and configure without external fetches.
Yet most deployments stop short of making command-line tools truly smooth. Missing shell completion means missed productivity. In production-grade air-gapped setups, that gap compounds into wasted minutes, typing errors, and slower responses when something breaks.
Shell completion in an air-gapped deployment demands clean packaging. The scripts and definition files must be bundled with the binary or baked into the release artifacts. Every dependency—whether Bash, Zsh, or Fish completion—needs to be prebuilt and placed in known directories. If your process tries to reach out to fetch them later, it fails.
The process is straightforward to automate. Start by exporting completion scripts in your build pipeline. Store them in your artifact repository alongside the main executables. During deployment, push those files into the correct shell path:
/etc/bash_completion.d/ for Bashshare/zsh/site-functions/ for Zshshare/fish/vendor_completions.d/ for Fish
Test the completion directly on the target machine before finalizing the image. Confirm no call is made to external networks. Log that check like any other deployment verification. This keeps your environment consistent across machines, rebuilds, and future upgrades.
An air-gapped deployment without shell completion is a halfway solution. Fully integrated completion transforms command-line workflows from slow and error-prone to fast and reliable. The goal is automation without the internet, efficiency without compromise, and clarity without waiting for a lookup.
This is exactly the kind of problem we designed to disappear. See it live in minutes at hoop.dev — and watch your air-gapped shell work like it should, from the very first command.