Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ brews:
install: |
bin.install "aicr"
bin.install "aicr-attestation.sigstore.json" if File.exist? "aicr-attestation.sigstore.json"
generate_completions_from_executable(bin/"aicr", "completion")
test: |
assert_match version.to_s, shell_output("#{bin}/aicr version")
caveats: |
Expand Down
49 changes: 36 additions & 13 deletions docs/user/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ This script:
- Detects your OS and architecture automatically
- Downloads the appropriate binary from GitHub releases
- Installs to `/usr/local/bin/aicr` by default (use `-d <dir>` for a custom location)
- Installs shell completions for bash, zsh, and fish (set `AICR_NO_COMPLETIONS=1` to skip)
- Verifies the installation
- Uses `GITHUB_TOKEN` environment variable for authenticated API calls (avoids rate limits)

Expand Down Expand Up @@ -99,26 +100,41 @@ Expected output shows version information and available commands.

## Post-Installation

### Shell Completion (Optional)
### Shell Completion

Enable shell auto-completion for command and flag names:
Tab completion for commands and flags is installed automatically by both the Homebrew formula and the install script. No manual setup is required.

**Opt out** (install script only): set `AICR_NO_COMPLETIONS=1` before running the script:

**Bash:**
```shell
# Add to ~/.bashrc
source <(aicr completion bash)
AICR_NO_COMPLETIONS=1 curl -sfL https://raw.githubusercontent.com/NVIDIA/aicr/main/install | bash -s --
```

**Zsh:**
**Manual setup** (build from source or `go install`):

Bash:
```shell
# Add to ~/.zshrc
source <(aicr completion zsh)
aicr completion bash > "${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}/completions/aicr"
```

Zsh:
```shell
aicr completion zsh > "${XDG_DATA_HOME:-$HOME/.local/share}/zsh/site-functions/_aicr"
```

**Fish:**
Fish:
```shell
# Add to ~/.config/fish/config.fish
aicr completion fish | source
aicr completion fish > ~/.config/fish/completions/aicr.fish
```

Alternatively, source completions dynamically in your shell RC file (evaluates on every shell start):

```shell
# Bash (~/.bashrc)
source <(aicr completion bash)

# Zsh (~/.zshrc)
source <(aicr completion zsh)
```

## Container Images
Expand Down Expand Up @@ -180,8 +196,15 @@ nvidia-smi
# Remove binary
sudo rm /usr/local/bin/aicr

# Remove shell completion (if configured)
# Remove the source line from your shell RC file
# Remove shell completions (remove whichever exist)
sudo rm -f /usr/share/bash-completion/completions/aicr
sudo rm -f /usr/local/share/zsh/site-functions/_aicr
sudo rm -f /opt/homebrew/share/zsh/site-functions/_aicr
sudo rm -f /opt/homebrew/etc/bash_completion.d/aicr
sudo rm -f /usr/local/etc/bash_completion.d/aicr
rm -f "${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion/completions/aicr"
rm -f "${XDG_DATA_HOME:-$HOME/.local/share}/zsh/site-functions/_aicr"
rm -f "${XDG_CONFIG_HOME:-$HOME/.config}/fish/completions/aicr.fish"
```

## Getting Help
Expand Down
104 changes: 103 additions & 1 deletion install
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ Install utility for $BIN_NAME
Usage: $0 [-d install_dir]

Environment Variables:
GITHUB_TOKEN GitHub token to avoid API rate limits (no special scopes required)
GITHUB_TOKEN GitHub token to avoid API rate limits (no special scopes required)
AICR_NO_COMPLETIONS Set to 1 to skip shell completion installation

Examples:
$0 # Install to /usr/local/bin
Expand Down Expand Up @@ -106,6 +107,102 @@ get_archive_name() {
echo "${BIN_NAME}_${ver}_${2}_${3}.tar.gz" # version, os, arch
}

# ==============================================================================
# Shell Completion Setup
# ==============================================================================

write_completion() {
local bin_path="$1" shell="$2" target="$3"
local target_dir tmp_file
target_dir=$(dirname "$target")
mkdir -p "$target_dir" 2>/dev/null || sudo mkdir -p "$target_dir" 2>/dev/null || return 1
tmp_file=$(mktemp) || return 1
if ! "$bin_path" completion "$shell" > "$tmp_file" 2>/dev/null || [[ ! -s "$tmp_file" ]]; then
rm -f "$tmp_file"
return 1
fi
chmod 644 "$tmp_file"
if [[ -w "$target_dir" ]]; then
mv "$tmp_file" "$target" || { rm -f "$tmp_file"; return 1; }
else
sudo mv "$tmp_file" "$target" || { rm -f "$tmp_file"; return 1; }
fi
}

setup_bash_completions() {
local bin_path="$1" os="$2" xdg_data="$3" user_only="$4"
local sys_dir
if [[ "$os" == "darwin" ]]; then
local brew_prefix="/usr/local"
[[ -d /opt/homebrew ]] && brew_prefix="/opt/homebrew"
sys_dir="${brew_prefix}/etc/bash_completion.d"
else
sys_dir="/usr/share/bash-completion/completions"
fi

if [[ "$user_only" != "true" ]] && write_completion "$bin_path" bash "${sys_dir}/aicr"; then
ok "Bash completions installed"
elif write_completion "$bin_path" bash "${xdg_data}/bash-completion/completions/aicr"; then
ok "Bash completions installed (user-local)"
else
warn "Could not install bash completions"
fi
}

setup_zsh_completions() {
local bin_path="$1" os="$2" xdg_data="$3" user_only="$4"
local sys_dir
if [[ "$os" == "darwin" ]]; then
local brew_prefix="/usr/local"
[[ -d /opt/homebrew ]] && brew_prefix="/opt/homebrew"
sys_dir="${brew_prefix}/share/zsh/site-functions"
else
sys_dir="/usr/local/share/zsh/site-functions"
fi

if [[ "$user_only" != "true" ]] && write_completion "$bin_path" zsh "${sys_dir}/_aicr"; then
ok "Zsh completions installed"
elif write_completion "$bin_path" zsh "${xdg_data}/zsh/site-functions/_aicr"; then
ok "Zsh completions installed (user-local)"
else
warn "Could not install zsh completions"
fi
}

setup_fish_completions() {
local bin_path="$1" user_only="$2"
local sys_dir="/usr/share/fish/vendor_completions.d"
local user_dir="${XDG_CONFIG_HOME:-$HOME/.config}/fish/completions"

if [[ "$user_only" != "true" ]] && [[ -d "$sys_dir" ]] && write_completion "$bin_path" fish "${sys_dir}/aicr.fish"; then
ok "Fish completions installed"
elif [[ -d "${user_dir%/*}" ]] && write_completion "$bin_path" fish "${user_dir}/aicr.fish"; then
ok "Fish completions installed (user-local)"
fi
}

setup_completions() {
if [[ "${AICR_NO_COMPLETIONS:-0}" == "1" ]]; then
info "Skipping shell completion setup (AICR_NO_COMPLETIONS=1)"
return 0
fi

local bin_path="${INSTALL_DIR}/${BIN_NAME}"
local os xdg_data user_only="false"
os=$(get_os)
xdg_data="${XDG_DATA_HOME:-$HOME/.local/share}"

# If the binary install did not need sudo, skip system completion dirs
# to avoid unexpected sudo prompts (e.g., ./install -d ~/bin).
[[ "${USED_SUDO:-false}" == "false" ]] && user_only="true"

step "Setting up shell completions..."

setup_bash_completions "$bin_path" "$os" "$xdg_data" "$user_only"
setup_zsh_completions "$bin_path" "$os" "$xdg_data" "$user_only"
setup_fish_completions "$bin_path" "$user_only"
}

# ==============================================================================
# GitHub API Functions
# ==============================================================================
Expand Down Expand Up @@ -297,11 +394,13 @@ main() {
chmod +x "${temp_dir}/${BIN_NAME}"
step "Installing $BIN_NAME to $INSTALL_DIR"
mkdir -p "$INSTALL_DIR"
USED_SUDO=false
if [[ -w "$INSTALL_DIR" ]]; then
mv "${temp_dir}/${BIN_NAME}" "${INSTALL_DIR}/${BIN_NAME}"
[[ -f "${temp_dir}/${BIN_NAME}-attestation.sigstore.json" ]] && \
mv "${temp_dir}/${BIN_NAME}-attestation.sigstore.json" "${INSTALL_DIR}/${BIN_NAME}-attestation.sigstore.json"
else
USED_SUDO=true
sudo mv "${temp_dir}/${BIN_NAME}" "${INSTALL_DIR}/${BIN_NAME}"
[[ -f "${temp_dir}/${BIN_NAME}-attestation.sigstore.json" ]] && \
sudo mv "${temp_dir}/${BIN_NAME}-attestation.sigstore.json" "${INSTALL_DIR}/${BIN_NAME}-attestation.sigstore.json"
Expand All @@ -313,6 +412,9 @@ main() {
[[ -f "${INSTALL_DIR}/${BIN_NAME}-attestation.sigstore.json" ]] && \
msg "Attestation: ${INSTALL_DIR}/${BIN_NAME}-attestation.sigstore.json"

# Install shell completions
setup_completions || warn "Shell completion setup failed (non-fatal)"

# Fetch latest Sigstore trusted root for offline verification.
# The trusted root enables 'aicr verify' to check attestation signatures
# without contacting Sigstore infrastructure. If this fails (e.g., no network),
Expand Down
Loading