diff --git a/50-ollama-completion b/50-ollama-completion new file mode 100755 index 0000000..3641d22 --- /dev/null +++ b/50-ollama-completion @@ -0,0 +1,149 @@ +# shellcheck shell=bash +# shellcheck disable=SC2207 # Standard pattern for bash completions +# Bash completion for Ollama CLI +# Hand-written because ollama does not yet expose a "completion" subcommand. +# TODO: Replace with cached_completion once "ollama completion bash" is available. + +command -v ollama &>/dev/null || return + +_ollama_models() { + # List locally available model names (NAME column, strip tag if ":latest") + ollama list 2>/dev/null | awk 'NR>1 {print $1}' +} + +_ollama_running_models() { + # List currently running model names + ollama ps 2>/dev/null | awk 'NR>1 {print $1}' +} + +_ollama_launch_integrations() { + printf '%s\n' claude cline codex droid opencode openclaw clawdbot moltbot pi +} + +_ollama_completions() { + local cur prev + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + local commands="serve create show run stop pull push signin signout list ls ps cp rm launch help" + + local global_opts="--help --nowordwrap --verbose --version" + + # Subcommand-specific flags + case "${prev}" in + run) + COMPREPLY=( $(compgen -W "$(_ollama_models)" -- "${cur}") ) + return 0 + ;; + show) + COMPREPLY=( $(compgen -W "$(_ollama_models)" -- "${cur}") ) + return 0 + ;; + stop) + COMPREPLY=( $(compgen -W "$(_ollama_running_models)" -- "${cur}") ) + return 0 + ;; + rm) + COMPREPLY=( $(compgen -W "$(_ollama_models)" -- "${cur}") ) + return 0 + ;; + cp) + COMPREPLY=( $(compgen -W "$(_ollama_models)" -- "${cur}") ) + return 0 + ;; + push) + COMPREPLY=( $(compgen -W "$(_ollama_models)" -- "${cur}") ) + return 0 + ;; + pull) + # No local completions useful for pull (user types a registry name) + return 0 + ;; + launch) + COMPREPLY=( $(compgen -W "$(_ollama_launch_integrations)" -- "${cur}") ) + return 0 + ;; + help) + COMPREPLY=( $(compgen -W "${commands}" -- "${cur}") ) + return 0 + ;; + # Flag-specific value completions + --format) + COMPREPLY=( $(compgen -W "json" -- "${cur}") ) + return 0 + ;; + --quantize|-q) + COMPREPLY=( $(compgen -W "q4_0 q4_1 q4_K_S q4_K_M q5_0 q5_1 q5_K_S q5_K_M q8_0" -- "${cur}") ) + return 0 + ;; + --file|-f) + COMPREPLY=( $(compgen -f -- "${cur}") ) + return 0 + ;; + --model) + COMPREPLY=( $(compgen -W "$(_ollama_models)" -- "${cur}") ) + return 0 + ;; + esac + + # Determine which subcommand we're in (if any) + local subcmd="" + local i + for (( i=1; i < COMP_CWORD; i++ )); do + case "${COMP_WORDS[i]}" in + run|show|stop|pull|push|cp|rm|create|serve|list|ls|ps|launch|signin|signout|help) + subcmd="${COMP_WORDS[i]}" + break + ;; + esac + done + + # Per-subcommand flag completion + if [[ "${cur}" == -* ]]; then + local sub_opts="" + case "${subcmd}" in + run) + sub_opts="--format --insecure --keepalive --nowordwrap --verbose + --hidethinking --think --experimental --experimental-websearch + --experimental-yolo --dimensions --truncate + --width --height --steps --seed --negative" + ;; + show) + sub_opts="--license --modelfile --parameters --system --template --verbose" + ;; + pull|push) + sub_opts="--insecure" + ;; + create) + sub_opts="--file --quantize --experimental" + ;; + launch) + sub_opts="--config --model --yes" + ;; + esac + COMPREPLY=( $(compgen -W "${sub_opts} --help" -- "${cur}") ) + return 0 + fi + + # Handle model-name completion for rm (supports multiple models) + if [[ "${subcmd}" == "rm" ]]; then + COMPREPLY=( $(compgen -W "$(_ollama_models)" -- "${cur}") ) + return 0 + fi + + # Handle second argument for cp (destination) + if [[ "${subcmd}" == "cp" && ${COMP_CWORD} -ge 3 ]]; then + COMPREPLY=( $(compgen -W "$(_ollama_models)" -- "${cur}") ) + return 0 + fi + + # Top-level: complete subcommands and global options + if [[ ${COMP_CWORD} -eq 1 ]]; then + COMPREPLY=( $(compgen -W "${commands} ${global_opts}" -- "${cur}") ) + fi + + return 0 +} + +complete -F _ollama_completions ollama