diff --git a/cmd/generate_changelog/incoming/1689.txt b/cmd/generate_changelog/incoming/1689.txt
new file mode 100644
index 00000000..70f258d1
--- /dev/null
+++ b/cmd/generate_changelog/incoming/1689.txt
@@ -0,0 +1,7 @@
+### PR [#1689](https://github.com/danielmiessler/Fabric/pull/1689) by [ksylvan](https://github.com/ksylvan): Enhanced Shell Completions for Fabric CLI Binaries
+
+- Add 'fabric-ai' alias support across all shell completions
+- Use invoked command name for dynamic completion list queries
+- Refactor fish completions into reusable registrar for multiple commands
+- Update Bash completion to reference executable via COMP_WORDS[0]
+- Install completions automatically with new cross-shell setup script
diff --git a/completions/_fabric b/completions/_fabric
index 34d199ed..be6f0ba1 100644
--- a/completions/_fabric
+++ b/completions/_fabric
@@ -1,47 +1,54 @@
-#compdef fabric
+#compdef fabric fabric-ai
# Zsh completion for fabric CLI
# Place this file in a directory in your $fpath (e.g. /usr/local/share/zsh/site-functions)
_fabric_patterns() {
local -a patterns
- patterns=(${(f)"$(fabric --listpatterns --shell-complete-list 2>/dev/null)"})
+ local cmd=${words[1]}
+ patterns=(${(f)"$($cmd --listpatterns --shell-complete-list 2>/dev/null)"})
compadd -X "Patterns:" ${patterns}
}
_fabric_models() {
local -a models
- models=(${(f)"$(fabric --listmodels --shell-complete-list 2>/dev/null)"})
+ local cmd=${words[1]}
+ models=(${(f)"$($cmd --listmodels --shell-complete-list 2>/dev/null)"})
compadd -X "Models:" ${models}
}
_fabric_contexts() {
local -a contexts
- contexts=(${(f)"$(fabric --listcontexts --shell-complete-list 2>/dev/null)"})
+ local cmd=${words[1]}
+ contexts=(${(f)"$($cmd --listcontexts --shell-complete-list 2>/dev/null)"})
compadd -X "Contexts:" ${contexts}
}
_fabric_sessions() {
local -a sessions
- sessions=(${(f)"$(fabric --listsessions --shell-complete-list 2>/dev/null)"})
+ local cmd=${words[1]}
+ sessions=(${(f)"$($cmd --listsessions --shell-complete-list 2>/dev/null)"})
compadd -X "Sessions:" ${sessions}
}
_fabric_strategies() {
local -a strategies
- strategies=(${(f)"$(fabric --liststrategies --shell-complete-list 2>/dev/null)"})
+ local cmd=${words[1]}
+ strategies=(${(f)"$($cmd --liststrategies --shell-complete-list 2>/dev/null)"})
compadd -X "Strategies:" ${strategies}
}
_fabric_extensions() {
local -a extensions
- extensions=(${(f)"$(fabric --listextensions --shell-complete-list 2>/dev/null)"})
+ local cmd=${words[1]}
+ extensions=(${(f)"$($cmd --listextensions --shell-complete-list 2>/dev/null)"})
compadd -X "Extensions:" ${extensions}
}
_fabric_gemini_voices() {
local -a voices
- voices=(${(f)"$(fabric --list-gemini-voices --shell-complete-list 2>/dev/null)"})
+ local cmd=${words[1]}
+ voices=(${(f)"$($cmd --list-gemini-voices --shell-complete-list 2>/dev/null)"})
compadd -X "Gemini TTS Voices:" ${voices}
}
diff --git a/completions/fabric.bash b/completions/fabric.bash
index e5d345f5..376f7a06 100644
--- a/completions/fabric.bash
+++ b/completions/fabric.bash
@@ -17,7 +17,7 @@ _fabric() {
# Helper function for dynamic completions
_fabric_get_list() {
- fabric "$1" --shell-complete-list 2>/dev/null
+ "${COMP_WORDS[0]}" "$1" --shell-complete-list 2>/dev/null
}
# Handle completions based on the previous word
@@ -104,4 +104,4 @@ _fabric() {
}
-complete -F _fabric fabric
+complete -F _fabric fabric fabric-ai
diff --git a/completions/fabric.fish b/completions/fabric.fish
index d5b29976..50dc265f 100755
--- a/completions/fabric.fish
+++ b/completions/fabric.fish
@@ -8,107 +8,120 @@
# Helper functions for dynamic completions
function __fabric_get_patterns
- fabric --listpatterns --shell-complete-list 2>/dev/null
+ set cmd (commandline -opc)[1]
+ $cmd --listpatterns --shell-complete-list 2>/dev/null
end
function __fabric_get_models
- fabric --listmodels --shell-complete-list 2>/dev/null
+ set cmd (commandline -opc)[1]
+ $cmd --listmodels --shell-complete-list 2>/dev/null
end
function __fabric_get_contexts
- fabric --listcontexts --shell-complete-list 2>/dev/null
+ set cmd (commandline -opc)[1]
+ $cmd --listcontexts --shell-complete-list 2>/dev/null
end
function __fabric_get_sessions
- fabric --listsessions --shell-complete-list 2>/dev/null
+ set cmd (commandline -opc)[1]
+ $cmd --listsessions --shell-complete-list 2>/dev/null
end
function __fabric_get_strategies
- fabric --liststrategies --shell-complete-list 2>/dev/null
+ set cmd (commandline -opc)[1]
+ $cmd --liststrategies --shell-complete-list 2>/dev/null
end
function __fabric_get_extensions
- fabric --listextensions --shell-complete-list 2>/dev/null
+ set cmd (commandline -opc)[1]
+ $cmd --listextensions --shell-complete-list 2>/dev/null
end
function __fabric_get_gemini_voices
- fabric --list-gemini-voices --shell-complete-list 2>/dev/null
+ set cmd (commandline -opc)[1]
+ $cmd --list-gemini-voices --shell-complete-list 2>/dev/null
end
# Main completion function
-complete -c fabric -f
+function __fabric_register_completions
+ set cmd $argv[1]
+ complete -c $cmd -f
-# Flag completions with arguments
-complete -c fabric -s p -l pattern -d "Choose a pattern from the available patterns" -a "(__fabric_get_patterns)"
-complete -c fabric -s v -l variable -d "Values for pattern variables, e.g. -v=#role:expert -v=#points:30"
-complete -c fabric -s C -l context -d "Choose a context from the available contexts" -a "(__fabric_get_contexts)"
-complete -c fabric -l session -d "Choose a session from the available sessions" -a "(__fabric_get_sessions)"
-complete -c fabric -s a -l attachment -d "Attachment path or URL (e.g. for OpenAI image recognition messages)" -r
-complete -c fabric -s t -l temperature -d "Set temperature (default: 0.7)"
-complete -c fabric -s T -l topp -d "Set top P (default: 0.9)"
-complete -c fabric -s P -l presencepenalty -d "Set presence penalty (default: 0.0)"
-complete -c fabric -s F -l frequencypenalty -d "Set frequency penalty (default: 0.0)"
-complete -c fabric -s m -l model -d "Choose model" -a "(__fabric_get_models)"
-complete -c fabric -l modelContextLength -d "Model context length (only affects ollama)"
-complete -c fabric -s o -l output -d "Output to file" -r
-complete -c fabric -s n -l latest -d "Number of latest patterns to list (default: 0)"
-complete -c fabric -s y -l youtube -d "YouTube video or play list URL to grab transcript, comments from it"
-complete -c fabric -s g -l language -d "Specify the Language Code for the chat, e.g. -g=en -g=zh"
-complete -c fabric -s u -l scrape_url -d "Scrape website URL to markdown using Jina AI"
-complete -c fabric -s q -l scrape_question -d "Search question using Jina AI"
-complete -c fabric -s e -l seed -d "Seed to be used for LMM generation"
-complete -c fabric -s w -l wipecontext -d "Wipe context" -a "(__fabric_get_contexts)"
-complete -c fabric -s W -l wipesession -d "Wipe session" -a "(__fabric_get_sessions)"
-complete -c fabric -l printcontext -d "Print context" -a "(__fabric_get_contexts)"
-complete -c fabric -l printsession -d "Print session" -a "(__fabric_get_sessions)"
-complete -c fabric -l address -d "The address to bind the REST API (default: :8080)"
-complete -c fabric -l api-key -d "API key used to secure server routes"
-complete -c fabric -l config -d "Path to YAML config file" -r -a "*.yaml *.yml"
-complete -c fabric -l search-location -d "Set location for web search results (e.g., 'America/Los_Angeles')"
-complete -c fabric -l image-file -d "Save generated image to specified file path (e.g., 'output.png')" -r -a "*.png *.webp *.jpeg *.jpg"
-complete -c fabric -l image-size -d "Image dimensions: 1024x1024, 1536x1024, 1024x1536, auto (default: auto)" -a "1024x1024 1536x1024 1024x1536 auto"
-complete -c fabric -l image-quality -d "Image quality: low, medium, high, auto (default: auto)" -a "low medium high auto"
-complete -c fabric -l image-compression -d "Compression level 0-100 for JPEG/WebP formats (default: not set)" -r
-complete -c fabric -l image-background -d "Background type: opaque, transparent (default: opaque, only for PNG/WebP)" -a "opaque transparent"
-complete -c fabric -l addextension -d "Register a new extension from config file path" -r -a "*.yaml *.yml"
-complete -c fabric -l rmextension -d "Remove a registered extension by name" -a "(__fabric_get_extensions)"
-complete -c fabric -l strategy -d "Choose a strategy from the available strategies" -a "(__fabric_get_strategies)"
-complete -c fabric -l think-start-tag -d "Start tag for thinking sections (default: )"
-complete -c fabric -l think-end-tag -d "End tag for thinking sections (default: )"
-complete -c fabric -l voice -d "TTS voice name for supported models (e.g., Kore, Charon, Puck)" -a "(__fabric_get_gemini_voices)"
-complete -c fabric -l notification-command -d "Custom command to run for notifications (overrides built-in notifications)"
+ # Flag completions with arguments
+ complete -c $cmd -s p -l pattern -d "Choose a pattern from the available patterns" -a "(__fabric_get_patterns)"
+ complete -c $cmd -s v -l variable -d "Values for pattern variables, e.g. -v=#role:expert -v=#points:30"
+ complete -c $cmd -s C -l context -d "Choose a context from the available contexts" -a "(__fabric_get_contexts)"
+ complete -c $cmd -l session -d "Choose a session from the available sessions" -a "(__fabric_get_sessions)"
+ complete -c $cmd -s a -l attachment -d "Attachment path or URL (e.g. for OpenAI image recognition messages)" -r
+ complete -c $cmd -s t -l temperature -d "Set temperature (default: 0.7)"
+ complete -c $cmd -s T -l topp -d "Set top P (default: 0.9)"
+ complete -c $cmd -s P -l presencepenalty -d "Set presence penalty (default: 0.0)"
+ complete -c $cmd -s F -l frequencypenalty -d "Set frequency penalty (default: 0.0)"
+ complete -c $cmd -s m -l model -d "Choose model" -a "(__fabric_get_models)"
+ complete -c $cmd -l modelContextLength -d "Model context length (only affects ollama)"
+ complete -c $cmd -s o -l output -d "Output to file" -r
+ complete -c $cmd -s n -l latest -d "Number of latest patterns to list (default: 0)"
+ complete -c $cmd -s y -l youtube -d "YouTube video or play list URL to grab transcript, comments from it"
+ complete -c $cmd -s g -l language -d "Specify the Language Code for the chat, e.g. -g=en -g=zh"
+ complete -c $cmd -s u -l scrape_url -d "Scrape website URL to markdown using Jina AI"
+ complete -c $cmd -s q -l scrape_question -d "Search question using Jina AI"
+ complete -c $cmd -s e -l seed -d "Seed to be used for LMM generation"
+ complete -c $cmd -s w -l wipecontext -d "Wipe context" -a "(__fabric_get_contexts)"
+ complete -c $cmd -s W -l wipesession -d "Wipe session" -a "(__fabric_get_sessions)"
+ complete -c $cmd -l printcontext -d "Print context" -a "(__fabric_get_contexts)"
+ complete -c $cmd -l printsession -d "Print session" -a "(__fabric_get_sessions)"
+ complete -c $cmd -l address -d "The address to bind the REST API (default: :8080)"
+ complete -c $cmd -l api-key -d "API key used to secure server routes"
+ complete -c $cmd -l config -d "Path to YAML config file" -r -a "*.yaml *.yml"
+ complete -c $cmd -l search-location -d "Set location for web search results (e.g., 'America/Los_Angeles')"
+ complete -c $cmd -l image-file -d "Save generated image to specified file path (e.g., 'output.png')" -r -a "*.png *.webp *.jpeg *.jpg"
+ complete -c $cmd -l image-size -d "Image dimensions: 1024x1024, 1536x1024, 1024x1536, auto (default: auto)" -a "1024x1024 1536x1024 1024x1536 auto"
+ complete -c $cmd -l image-quality -d "Image quality: low, medium, high, auto (default: auto)" -a "low medium high auto"
+ complete -c $cmd -l image-compression -d "Compression level 0-100 for JPEG/WebP formats (default: not set)" -r
+ complete -c $cmd -l image-background -d "Background type: opaque, transparent (default: opaque, only for PNG/WebP)" -a "opaque transparent"
+ complete -c $cmd -l addextension -d "Register a new extension from config file path" -r -a "*.yaml *.yml"
+ complete -c $cmd -l rmextension -d "Remove a registered extension by name" -a "(__fabric_get_extensions)"
+ complete -c $cmd -l strategy -d "Choose a strategy from the available strategies" -a "(__fabric_get_strategies)"
+ complete -c $cmd -l think-start-tag -d "Start tag for thinking sections (default: )"
+ complete -c $cmd -l think-end-tag -d "End tag for thinking sections (default: )"
+ complete -c $cmd -l voice -d "TTS voice name for supported models (e.g., Kore, Charon, Puck)" -a "(__fabric_get_gemini_voices)"
+ complete -c $cmd -l notification-command -d "Custom command to run for notifications (overrides built-in notifications)"
-# Boolean flags (no arguments)
-complete -c fabric -s S -l setup -d "Run setup for all reconfigurable parts of fabric"
-complete -c fabric -s s -l stream -d "Stream"
-complete -c fabric -s r -l raw -d "Use the defaults of the model without sending chat options"
-complete -c fabric -s l -l listpatterns -d "List all patterns"
-complete -c fabric -s L -l listmodels -d "List all available models"
-complete -c fabric -s x -l listcontexts -d "List all contexts"
-complete -c fabric -s X -l listsessions -d "List all sessions"
-complete -c fabric -s U -l updatepatterns -d "Update patterns"
-complete -c fabric -s c -l copy -d "Copy to clipboard"
-complete -c fabric -l output-session -d "Output the entire session to the output file"
-complete -c fabric -s d -l changeDefaultModel -d "Change default model"
-complete -c fabric -l playlist -d "Prefer playlist over video if both ids are present in the URL"
-complete -c fabric -l transcript -d "Grab transcript from YouTube video and send to chat"
-complete -c fabric -l transcript-with-timestamps -d "Grab transcript from YouTube video with timestamps"
-complete -c fabric -l comments -d "Grab comments from YouTube video and send to chat"
-complete -c fabric -l metadata -d "Output video metadata"
-complete -c fabric -l yt-dlp-args -d "Additional arguments to pass to yt-dlp (e.g. '--cookies-from-browser brave')"
-complete -c fabric -l readability -d "Convert HTML input into a clean, readable view"
-complete -c fabric -l input-has-vars -d "Apply variables to user input"
-complete -c fabric -l dry-run -d "Show what would be sent to the model without actually sending it"
-complete -c fabric -l search -d "Enable web search tool for supported models (Anthropic, OpenAI, Gemini)"
-complete -c fabric -l serve -d "Serve the Fabric Rest API"
-complete -c fabric -l serveOllama -d "Serve the Fabric Rest API with ollama endpoints"
-complete -c fabric -l version -d "Print current version"
-complete -c fabric -l listextensions -d "List all registered extensions"
-complete -c fabric -l liststrategies -d "List all strategies"
-complete -c fabric -l listvendors -d "List all vendors"
-complete -c fabric -l list-gemini-voices -d "List all available Gemini TTS voices"
-complete -c fabric -l shell-complete-list -d "Output raw list without headers/formatting (for shell completion)"
-complete -c fabric -l suppress-think -d "Suppress text enclosed in thinking tags"
-complete -c fabric -l disable-responses-api -d "Disable OpenAI Responses API (default: false)"
-complete -c fabric -l notification -d "Send desktop notification when command completes"
-complete -c fabric -s h -l help -d "Show this help message"
+ # Boolean flags (no arguments)
+ complete -c $cmd -s S -l setup -d "Run setup for all reconfigurable parts of fabric"
+ complete -c $cmd -s s -l stream -d "Stream"
+ complete -c $cmd -s r -l raw -d "Use the defaults of the model without sending chat options"
+ complete -c $cmd -s l -l listpatterns -d "List all patterns"
+ complete -c $cmd -s L -l listmodels -d "List all available models"
+ complete -c $cmd -s x -l listcontexts -d "List all contexts"
+ complete -c $cmd -s X -l listsessions -d "List all sessions"
+ complete -c $cmd -s U -l updatepatterns -d "Update patterns"
+ complete -c $cmd -s c -l copy -d "Copy to clipboard"
+ complete -c $cmd -l output-session -d "Output the entire session to the output file"
+ complete -c $cmd -s d -l changeDefaultModel -d "Change default model"
+ complete -c $cmd -l playlist -d "Prefer playlist over video if both ids are present in the URL"
+ complete -c $cmd -l transcript -d "Grab transcript from YouTube video and send to chat"
+ complete -c $cmd -l transcript-with-timestamps -d "Grab transcript from YouTube video with timestamps"
+ complete -c $cmd -l comments -d "Grab comments from YouTube video and send to chat"
+ complete -c $cmd -l metadata -d "Output video metadata"
+ complete -c $cmd -l yt-dlp-args -d "Additional arguments to pass to yt-dlp (e.g. '--cookies-from-browser brave')"
+ complete -c $cmd -l readability -d "Convert HTML input into a clean, readable view"
+ complete -c $cmd -l input-has-vars -d "Apply variables to user input"
+ complete -c $cmd -l dry-run -d "Show what would be sent to the model without actually sending it"
+ complete -c $cmd -l search -d "Enable web search tool for supported models (Anthropic, OpenAI, Gemini)"
+ complete -c $cmd -l serve -d "Serve the Fabric Rest API"
+ complete -c $cmd -l serveOllama -d "Serve the Fabric Rest API with ollama endpoints"
+ complete -c $cmd -l version -d "Print current version"
+ complete -c $cmd -l listextensions -d "List all registered extensions"
+ complete -c $cmd -l liststrategies -d "List all strategies"
+ complete -c $cmd -l listvendors -d "List all vendors"
+ complete -c $cmd -l list-gemini-voices -d "List all available Gemini TTS voices"
+ complete -c $cmd -l shell-complete-list -d "Output raw list without headers/formatting (for shell completion)"
+ complete -c $cmd -l suppress-think -d "Suppress text enclosed in thinking tags"
+ complete -c $cmd -l disable-responses-api -d "Disable OpenAI Responses API (default: false)"
+ complete -c $cmd -l notification -d "Send desktop notification when command completes"
+ complete -c $cmd -s h -l help -d "Show this help message"
+end
+
+__fabric_register_completions fabric
+__fabric_register_completions fabric-ai
diff --git a/completions/setup-completions.sh b/completions/setup-completions.sh
new file mode 100755
index 00000000..22f0259c
--- /dev/null
+++ b/completions/setup-completions.sh
@@ -0,0 +1,387 @@
+#!/bin/sh
+
+# Fabric Shell Completions Setup Script
+# This script automatically installs shell completions for the fabric CLI
+# based on your current shell and the installed fabric command name.
+
+set -e
+
+# Global variables
+DRY_RUN=false
+
+# Colors for output
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+BLUE='\033[0;34m'
+CYAN='\033[0;36m'
+NC='\033[0m' # No Color
+
+# Function to print colored output
+print_info() {
+ printf "${BLUE}[INFO]${NC} %s\n" "$1"
+}
+
+print_success() {
+ printf "${GREEN}[SUCCESS]${NC} %s\n" "$1"
+}
+
+print_warning() {
+ printf "${YELLOW}[WARNING]${NC} %s\n" "$1"
+}
+
+print_error() {
+ printf "${RED}[ERROR]${NC} %s\n" "$1"
+}
+
+print_dry_run() {
+ printf "${CYAN}[DRY-RUN]${NC} %s\n" "$1"
+}
+
+# Function to execute commands with dry-run support
+execute_command() {
+ cmd="$1"
+
+ if [ "$DRY_RUN" = true ]; then
+ print_dry_run "Would run: $cmd"
+ return 0
+ else
+ eval "$cmd" 2>/dev/null
+ fi
+}
+
+# Ensure directory exists, try sudo on permission failure
+ensure_dir() {
+ dir="$1"
+ # Expand ~ if present
+ case "$dir" in
+ ~/*)
+ dir="$HOME${dir#~}"
+ ;;
+ esac
+
+ if [ -d "$dir" ]; then
+ return 0
+ fi
+
+ if [ "$DRY_RUN" = true ]; then
+ print_dry_run "Would run: mkdir -p \"$dir\""
+ print_dry_run "If permission denied, would run: sudo mkdir -p \"$dir\""
+ return 0
+ fi
+
+ if mkdir -p "$dir" 2>/dev/null; then
+ return 0
+ fi
+ if command -v sudo >/dev/null 2>&1 && sudo mkdir -p "$dir" 2>/dev/null; then
+ return 0
+ fi
+ print_error "Failed to create directory: $dir"
+ return 1
+}
+
+# Copy file with sudo fallback on permission failure
+install_file() {
+ src="$1"
+ dest="$2"
+
+ if [ "$DRY_RUN" = true ]; then
+ print_dry_run "Would run: cp \"$src\" \"$dest\""
+ print_dry_run "If permission denied, would run: sudo cp \"$src\" \"$dest\""
+ return 0
+ fi
+
+ if cp "$src" "$dest" 2>/dev/null; then
+ return 0
+ fi
+ if command -v sudo >/dev/null 2>&1 && sudo cp "$src" "$dest" 2>/dev/null; then
+ return 0
+ fi
+ print_error "Failed to install file to: $dest"
+ return 1
+}
+
+# Function to detect fabric command name
+detect_fabric_command() {
+ if command -v fabric >/dev/null 2>&1; then
+ echo "fabric"
+ elif command -v fabric-ai >/dev/null 2>&1; then
+ echo "fabric-ai"
+ else
+ print_error "Neither 'fabric' nor 'fabric-ai' command found in PATH"
+ exit 1
+ fi
+}
+
+# Function to detect shell
+detect_shell() {
+ if [ -n "$SHELL" ]; then
+ basename "$SHELL"
+ else
+ print_warning "SHELL environment variable not set, defaulting to sh"
+ echo "sh"
+ fi
+}
+
+# Function to get script directory
+get_script_dir() {
+ # Get the directory where this script is located
+ script_path="$(readlink -f "$0" 2>/dev/null || realpath "$0" 2>/dev/null || echo "$0")"
+ dirname "$script_path"
+}
+
+# Function to setup Zsh completions
+setup_zsh_completions() {
+ fabric_cmd="$1"
+ script_dir="$2"
+ completion_file="_${fabric_cmd}"
+
+ print_info "Setting up Zsh completions for '$fabric_cmd'..."
+
+ # Try to use existing $fpath first, then fall back to default directories
+ zsh_dirs=""
+
+ # Check if user's shell is zsh and try to get fpath from it
+ if [ "$(basename "$SHELL")" = "zsh" ] && command -v zsh >/dev/null 2>&1; then
+ # Get fpath from zsh by sourcing user's .zshrc first
+ fpath_output=$(zsh -c "source \$HOME/.zshrc 2>/dev/null && print -l \$fpath" 2>/dev/null | head -5 | tr '\n' ' ')
+ if [ -n "$fpath_output" ] && [ "$fpath_output" != "" ]; then
+ print_info "Using directories from zsh \$fpath"
+ zsh_dirs="$fpath_output"
+ fi
+ fi
+
+ # If we couldn't get fpath or it's empty, use default directories
+ if [ -z "$zsh_dirs" ] || [ "$zsh_dirs" = "" ]; then
+ print_info "Using default zsh completion directories"
+ zsh_dirs="/usr/local/share/zsh/site-functions /opt/homebrew/share/zsh/site-functions /usr/share/zsh/site-functions ~/.local/share/zsh/site-functions"
+ fi
+
+ installed=false
+
+ for dir in $zsh_dirs; do
+ # Create directory (with sudo fallback if needed)
+ if ensure_dir "$dir"; then
+ if install_file "$script_dir/_fabric" "$dir/$completion_file"; then
+ if [ "$DRY_RUN" = true ]; then
+ print_success "Would install Zsh completion to: $dir/$completion_file"
+ else
+ print_success "Installed Zsh completion to: $dir/$completion_file"
+ fi
+ installed=true
+ break
+ fi
+ fi
+ done
+
+ if [ "$installed" = false ]; then
+ if [ "$DRY_RUN" = true ]; then
+ print_warning "Would attempt to install Zsh completions but no writable directory found."
+ else
+ print_error "Failed to install Zsh completions. Try running with sudo or check permissions."
+ return 1
+ fi
+ fi
+
+ if [ "$DRY_RUN" = true ]; then
+ print_info "Would suggest: Restart your shell or run 'autoload -U compinit && compinit' to enable completions."
+ else
+ print_info "Restart your shell or run 'autoload -U compinit && compinit' to enable completions."
+ fi
+}
+
+# Function to setup Bash completions
+setup_bash_completions() {
+ fabric_cmd="$1"
+ script_dir="$2"
+ completion_file="${fabric_cmd}.bash"
+
+ print_info "Setting up Bash completions for '$fabric_cmd'..."
+
+ # Try different completion directories
+ bash_dirs="/etc/bash_completion.d /usr/local/etc/bash_completion.d /opt/homebrew/etc/bash_completion.d ~/.local/share/bash-completion/completions"
+ installed=false
+
+ for dir in $bash_dirs; do
+ if ensure_dir "$dir"; then
+ if install_file "$script_dir/fabric.bash" "$dir/$completion_file"; then
+ if [ "$DRY_RUN" = true ]; then
+ print_success "Would install Bash completion to: $dir/$completion_file"
+ else
+ print_success "Installed Bash completion to: $dir/$completion_file"
+ fi
+ installed=true
+ break
+ fi
+ fi
+ done
+
+ if [ "$installed" = false ]; then
+ if [ "$DRY_RUN" = true ]; then
+ print_warning "Would attempt to install Bash completions but no writable directory found."
+ else
+ print_error "Failed to install Bash completions. Try running with sudo or check permissions."
+ return 1
+ fi
+ fi
+
+ if [ "$DRY_RUN" = true ]; then
+ print_info "Would suggest: Restart your shell or run 'source ~/.bashrc' to enable completions."
+ else
+ print_info "Restart your shell or run 'source ~/.bashrc' to enable completions."
+ fi
+}
+
+# Function to setup Fish completions
+setup_fish_completions() {
+ fabric_cmd="$1"
+ script_dir="$2"
+ completion_file="${fabric_cmd}.fish"
+
+ print_info "Setting up Fish completions for '$fabric_cmd'..."
+
+ # Fish completion directory
+ fish_dir="$HOME/.config/fish/completions"
+
+ if [ "$DRY_RUN" = true ]; then
+ print_dry_run "Would run: mkdir -p \"$fish_dir\""
+ print_dry_run "Would run: cp \"$script_dir/fabric.fish\" \"$fish_dir/$completion_file\""
+ print_success "Would install Fish completion to: $fish_dir/$completion_file"
+ print_info "Fish will automatically load the completions (no restart needed)."
+ elif mkdir -p "$fish_dir" 2>/dev/null; then
+ if cp "$script_dir/fabric.fish" "$fish_dir/$completion_file"; then
+ print_success "Installed Fish completion to: $fish_dir/$completion_file"
+ print_info "Fish will automatically load the completions (no restart needed)."
+ else
+ print_error "Failed to copy Fish completion file."
+ return 1
+ fi
+ else
+ print_error "Failed to create Fish completions directory: $fish_dir"
+ return 1
+ fi
+}
+
+# Function to setup completions for other shells
+setup_other_shell_completions() {
+ fabric_cmd="$1"
+ shell_name="$2"
+
+ print_warning "Shell '$shell_name' is not directly supported."
+ print_info "You can manually source the completion files:"
+ print_info " Bash-compatible: source $script_dir/fabric.bash"
+ print_info " Zsh-compatible: source $script_dir/_fabric"
+}
+
+# Function to show help
+show_help() {
+ cat << EOF
+Fabric Shell Completions Setup Script
+
+USAGE:
+ setup-completions.sh [OPTIONS]
+
+OPTIONS:
+ --dry-run Show what commands would be run without executing them
+ --help Show this help message
+
+DESCRIPTION:
+ This script automatically installs shell completions for the fabric CLI
+ based on your current shell and the installed fabric command name.
+
+ The script looks for completion files in the same directory as the script,
+ so it can be run from anywhere.
+
+ Supports: zsh, bash, fish
+
+ The script will:
+ 1. Detect whether 'fabric' or 'fabric-ai' is installed
+ 2. Detect your current shell from the SHELL environment variable
+ 3. Install the appropriate completion file with the correct name
+ 4. Try multiple standard completion directories
+
+EXAMPLES:
+ ./setup-completions.sh # Install completions
+ ./setup-completions.sh --dry-run # Show what would be done
+ ./setup-completions.sh --help # Show this help
+
+EOF
+}
+
+# Main function
+main() {
+ # Parse command line arguments
+ while [ $# -gt 0 ]; do
+ case "$1" in
+ --dry-run)
+ DRY_RUN=true
+ shift
+ ;;
+ --help|-h)
+ show_help
+ exit 0
+ ;;
+ *)
+ print_error "Unknown option: $1"
+ print_info "Use --help for usage information."
+ exit 1
+ ;;
+ esac
+ done
+
+ print_info "Fabric Shell Completions Setup"
+ print_info "==============================="
+
+ if [ "$DRY_RUN" = true ]; then
+ print_info "DRY RUN MODE - Commands will be shown but not executed"
+ print_info ""
+ fi
+
+ # Get script directory
+ script_dir="$(get_script_dir)"
+
+ # Check if completion files exist
+ if [ ! -f "$script_dir/_fabric" ] || [ ! -f "$script_dir/fabric.bash" ] || [ ! -f "$script_dir/fabric.fish" ]; then
+ print_error "Completion files not found. Make sure you're running this script from the fabric completions directory."
+ print_error "Expected files:"
+ print_error " $script_dir/_fabric"
+ print_error " $script_dir/fabric.bash"
+ print_error " $script_dir/fabric.fish"
+ exit 1
+ fi
+
+ # Detect fabric command
+ fabric_cmd="$(detect_fabric_command)"
+ print_info "Detected fabric command: $fabric_cmd"
+
+ # Detect shell
+ shell_name="$(detect_shell)"
+ print_info "Detected shell: $shell_name"
+
+ # Setup completions based on shell
+ case "$shell_name" in
+ zsh)
+ setup_zsh_completions "$fabric_cmd" "$script_dir"
+ ;;
+ bash)
+ setup_bash_completions "$fabric_cmd" "$script_dir"
+ ;;
+ fish)
+ setup_fish_completions "$fabric_cmd" "$script_dir"
+ ;;
+ *)
+ setup_other_shell_completions "$fabric_cmd" "$shell_name"
+ ;;
+ esac
+
+ if [ "$DRY_RUN" = true ]; then
+ print_success "Dry-run completed! The above commands would set up shell completions."
+ print_info "Run without --dry-run to actually install the completions."
+ else
+ print_success "Shell completion setup completed!"
+ print_info "You can now use tab completion with the '$fabric_cmd' command."
+ fi
+}
+
+# Run main function
+main "$@"
diff --git a/docs/Shell-Completions.md b/docs/Shell-Completions.md
new file mode 100644
index 00000000..7bfaee89
--- /dev/null
+++ b/docs/Shell-Completions.md
@@ -0,0 +1,124 @@
+# Shell Completions for Fabric
+
+Fabric comes with shell completion support for Zsh, Bash, and Fish shells. These completions provide intelligent tab-completion for commands, flags, patterns, models, contexts, and more.
+
+## Quick Setup (Automated)
+
+For a quick automated installation, use the setup script:
+
+```bash
+# Run the automated setup script
+./completions/setup-completions.sh
+
+# Or see what it would do first
+./completions/setup-completions.sh --dry-run
+```
+
+The script will:
+
+- Detect whether you have `fabric` or `fabric-ai` installed
+- Detect your current shell (zsh, bash, or fish)
+- Use your existing `$fpath` directories (for zsh) or standard completion directories
+- Install the completion file with the correct name
+- Provide instructions for enabling the completions
+
+For manual installation or troubleshooting, see the detailed instructions below.
+
+## Manual Installation
+
+### Zsh
+
+1. Copy the completion file to a directory in your `$fpath`:
+
+ ```bash
+ sudo cp completions/_fabric /usr/local/share/zsh/site-functions/
+ ```
+
+2. **Important**: If you installed fabric as `fabric-ai`, create a symlink so completions work:
+
+ ```bash
+ sudo ln -s /usr/local/share/zsh/site-functions/_fabric /usr/local/share/zsh/site-functions/_fabric-ai
+ ```
+
+3. Restart your shell or reload completions:
+
+ ```bash
+ autoload -U compinit && compinit
+ ```
+
+### Bash
+
+1. Copy the completion file to a standard completion directory:
+
+ ```bash
+ # System-wide installation
+ sudo cp completions/fabric.bash /etc/bash_completion.d/
+
+ # Or user-specific installation
+ mkdir -p ~/.local/share/bash-completion/completions/
+ cp completions/fabric.bash ~/.local/share/bash-completion/completions/fabric
+ ```
+
+2. **Important**: If you installed fabric as `fabric-ai`, create a symlink:
+
+ ```bash
+ # For system-wide installation
+ sudo ln -s /etc/bash_completion.d/fabric.bash /etc/bash_completion.d/fabric-ai.bash
+
+ # Or for user-specific installation
+ ln -s ~/.local/share/bash-completion/completions/fabric ~/.local/share/bash-completion/completions/fabric-ai
+ ```
+
+3. Restart your shell or source the completion:
+
+ ```bash
+ source ~/.bashrc
+ ```
+
+### Fish
+
+1. Copy the completion file to Fish's completion directory:
+
+ ```bash
+ mkdir -p ~/.config/fish/completions
+ cp completions/fabric.fish ~/.config/fish/completions/
+ ```
+
+2. **Important**: If you installed fabric as `fabric-ai`, create a symlink:
+
+ ```bash
+ ln -s ~/.config/fish/completions/fabric.fish ~/.config/fish/completions/fabric-ai.fish
+ ```
+
+3. Fish will automatically load the completions (no restart needed).
+
+## Features
+
+The completions provide intelligent suggestions for:
+
+- **Patterns**: Tab-complete available patterns with `-p` or `--pattern`
+- **Models**: Tab-complete available models with `-m` or `--model`
+- **Contexts**: Tab-complete contexts for context-related flags
+- **Sessions**: Tab-complete sessions for session-related flags
+- **Strategies**: Tab-complete available strategies
+- **Extensions**: Tab-complete registered extensions
+- **Gemini Voices**: Tab-complete TTS voices for `--voice`
+- **File paths**: Smart file completion for attachment, output, and config options
+- **Flag completion**: All available command-line flags and options
+
+## Alternative Installation Method
+
+You can also source the completion files directly in your shell's configuration file:
+
+- **Zsh**: Add to `~/.zshrc`: `source /path/to/fabric/completions/_fabric`
+- **Bash**: Add to `~/.bashrc`: `source /path/to/fabric/completions/fabric.bash`
+- **Fish**: The file-based installation method above is preferred for Fish
+
+## Troubleshooting
+
+- If completions don't work, ensure the completion files have proper permissions
+- For Zsh, verify that the completion directory is in your `$fpath`
+- If you renamed the fabric binary, make sure to create the appropriate symlinks as described above
+- Restart your shell after installation to ensure completions are loaded
+
+The completion system dynamically queries the fabric command for current patterns, models, and other resources, so your completions will always be up-to-date with your fabric installation.