diff --git a/shell-completions/README.md b/shell-completions/README.md new file mode 100644 index 0000000..d9f70cb --- /dev/null +++ b/shell-completions/README.md @@ -0,0 +1,81 @@ +# Claude Code CLI Shell Completions + +This directory contains tab completion scripts for the `claude` command in bash, fish, and zsh shells. + +## Installation + +### Bash Completion + +```bash +# Copy the completion script to a completion directory +sudo cp claude-completions.bash /etc/bash_completion.d/claude + +# Or for user-only installation: +mkdir -p ~/.local/share/bash-completion/completions +cp claude-completions.bash ~/.local/share/bash-completion/completions/claude + +# Reload bash completions +source /etc/bash_completion +# or restart your shell +``` + +### Fish Completion + +```bash +# Copy to fish completions directory +mkdir -p ~/.config/fish/completions +cp claude-completions.fish ~/.config/fish/completions/claude.fish + +# Fish will automatically load the completions +``` + +### Zsh Completion + +```zsh +# Copy to a directory in your fpath +mkdir -p ~/.local/share/zsh/site-functions +cp claude-completions.zsh ~/.local/share/zsh/site-functions/_claude + +# Add to your ~/.zshrc if not already present: +fpath=(~/.local/share/zsh/site-functions $fpath) + +# Reload completions +autoload -U compinit && compinit +``` + +## Features + +All completion scripts support: + +- ✅ Main command options (-d, --debug, --print, etc.) +- ✅ All subcommands (config, mcp, install, etc.) +- ✅ Nested subcommand options (config get/set, mcp add/remove) +- ✅ File/directory completion for relevant flags (--settings, --add-dir, --mcp-config) +- ✅ Choice completion for enums (--output-format, --permission-mode, --transport) +- ✅ Model name suggestions for --model and --fallback-model flags +- ✅ Help text and descriptions for all options + +## Usage Examples + +After installation, you can use tab completion: + +```bash +claude # Shows: config, mcp, install, etc. +claude -- # Shows all global options +claude config # Shows: get, set, list, add, etc. +claude mcp add -- # Shows: --scope, --transport, etc. +claude --output-format # Shows: text, json, stream-json +claude --model # Shows: sonnet, opus, haiku, etc. +``` + +## Testing + +Test the completions by typing commands and pressing Tab: + +- Basic command completion +- Option flag completion +- Subcommand completion +- Value completion for choice-based options +- File/directory completion for path options + +The completion scripts handle complex nested command structures and provide context-aware suggestions. diff --git a/shell-completions/claude-completions.bash b/shell-completions/claude-completions.bash new file mode 100644 index 0000000..e38a901 --- /dev/null +++ b/shell-completions/claude-completions.bash @@ -0,0 +1,256 @@ +#!/bin/bash + +_claude_completions() { + local cur prev words cword + _init_completion || return + + local commands="config mcp migrate-installer setup-token doctor update install" + local global_opts="-d --debug --verbose -p --print --output-format --input-format + --mcp-debug --dangerously-skip-permissions --allowedTools --disallowedTools + --mcp-config --append-system-prompt --permission-mode -c --continue + -r --resume --model --fallback-model --settings --add-dir --ide + --strict-mcp-config --session-id -v --version -h --help" + + # Handle subcommands + local i=1 + local subcommand="" + while [[ $i -lt $cword ]]; do + if [[ "${words[i]}" =~ ^(config|mcp|migrate-installer|setup-token|doctor|update|install)$ ]]; then + subcommand="${words[i]}" + break + fi + ((i++)) + done + + case "$subcommand" in + config) + _claude_config_completions + return + ;; + mcp) + _claude_mcp_completions + return + ;; + install) + _claude_install_completions + return + ;; + migrate-installer|setup-token|doctor|update) + # These commands have no additional options beyond --help + if [[ "$cur" == -* ]]; then + COMPREPLY=($(compgen -W "-h --help" -- "$cur")) + fi + return + ;; + esac + + # Handle global options that take values + case "$prev" in + --output-format) + COMPREPLY=($(compgen -W "text json stream-json" -- "$cur")) + return + ;; + --input-format) + COMPREPLY=($(compgen -W "text stream-json" -- "$cur")) + return + ;; + --permission-mode) + COMPREPLY=($(compgen -W "acceptEdits bypassPermissions default plan" -- "$cur")) + return + ;; + --model|--fallback-model) + COMPREPLY=($(compgen -W "sonnet opus haiku claude-sonnet-4-20250514" -- "$cur")) + return + ;; + --settings|--mcp-config) + _filedir + return + ;; + --add-dir) + _filedir -d + return + ;; + --session-id) + # No completion for UUID + return + ;; + --allowedTools|--disallowedTools|--append-system-prompt) + # No specific completion + return + ;; + -r|--resume) + # Session ID or interactive selection - no specific completion + return + ;; + esac + + # If current word starts with -, complete options + if [[ "$cur" == -* ]]; then + if [[ -z "$subcommand" ]]; then + COMPREPLY=($(compgen -W "$global_opts" -- "$cur")) + fi + return + fi + + # If no subcommand yet, complete subcommands + if [[ -z "$subcommand" ]]; then + COMPREPLY=($(compgen -W "$commands" -- "$cur")) + return + fi +} + +_claude_config_completions() { + local cur prev words cword + _init_completion || return + + local config_commands="get set remove rm list ls add help" + local config_opts="-g --global -h --help" + + # Find config subcommand + local i=2 # Skip 'claude' and 'config' + local config_subcommand="" + while [[ $i -lt $cword ]]; do + if [[ "${words[i]}" =~ ^(get|set|remove|rm|list|ls|add|help)$ ]]; then + config_subcommand="${words[i]}" + break + fi + ((i++)) + done + + case "$config_subcommand" in + get|set|remove|rm|add) + if [[ "$cur" == -* ]]; then + COMPREPLY=($(compgen -W "$config_opts" -- "$cur")) + elif [[ "$config_subcommand" == "help" ]]; then + COMPREPLY=($(compgen -W "$config_commands" -- "$cur")) + fi + return + ;; + list|ls) + if [[ "$cur" == -* ]]; then + COMPREPLY=($(compgen -W "$config_opts" -- "$cur")) + fi + return + ;; + help) + COMPREPLY=($(compgen -W "$config_commands" -- "$cur")) + return + ;; + esac + + # If no config subcommand yet + if [[ -z "$config_subcommand" ]]; then + if [[ "$cur" == -* ]]; then + COMPREPLY=($(compgen -W "$config_opts" -- "$cur")) + else + COMPREPLY=($(compgen -W "$config_commands" -- "$cur")) + fi + fi +} + +_claude_mcp_completions() { + local cur prev words cword + _init_completion || return + + local mcp_commands="serve add remove list get add-json add-from-claude-desktop reset-project-choices help" + local mcp_opts="-h --help" + + # Find mcp subcommand + local i=2 # Skip 'claude' and 'mcp' + local mcp_subcommand="" + while [[ $i -lt $cword ]]; do + if [[ "${words[i]}" =~ ^(serve|add|remove|list|get|add-json|add-from-claude-desktop|reset-project-choices|help)$ ]]; then + mcp_subcommand="${words[i]}" + break + fi + ((i++)) + done + + case "$prev" in + -s|--scope) + COMPREPLY=($(compgen -W "local user project" -- "$cur")) + return + ;; + -t|--transport) + COMPREPLY=($(compgen -W "stdio sse http" -- "$cur")) + return + ;; + -e|--env|-H|--header) + # No specific completion for environment variables or headers + return + ;; + esac + + case "$mcp_subcommand" in + serve) + local serve_opts="-p --port -h --help" + if [[ "$cur" == -* ]]; then + COMPREPLY=($(compgen -W "$serve_opts" -- "$cur")) + fi + return + ;; + add) + local add_opts="-s --scope -t --transport -e --env -H --header -h --help" + if [[ "$cur" == -* ]]; then + COMPREPLY=($(compgen -W "$add_opts" -- "$cur")) + fi + return + ;; + add-json) + local add_json_opts="-s --scope -h --help" + if [[ "$cur" == -* ]]; then + COMPREPLY=($(compgen -W "$add_json_opts" -- "$cur")) + fi + return + ;; + add-from-claude-desktop) + local add_desktop_opts="-s --scope -h --help" + if [[ "$cur" == -* ]]; then + COMPREPLY=($(compgen -W "$add_desktop_opts" -- "$cur")) + fi + return + ;; + remove|get) + if [[ "$cur" == -* ]]; then + COMPREPLY=($(compgen -W "$mcp_opts" -- "$cur")) + fi + return + ;; + list|reset-project-choices) + if [[ "$cur" == -* ]]; then + COMPREPLY=($(compgen -W "$mcp_opts" -- "$cur")) + fi + return + ;; + help) + COMPREPLY=($(compgen -W "$mcp_commands" -- "$cur")) + return + ;; + esac + + # If no mcp subcommand yet + if [[ -z "$mcp_subcommand" ]]; then + if [[ "$cur" == -* ]]; then + COMPREPLY=($(compgen -W "$mcp_opts" -- "$cur")) + else + COMPREPLY=($(compgen -W "$mcp_commands" -- "$cur")) + fi + fi +} + +_claude_install_completions() { + local cur prev words cword + _init_completion || return + + local install_opts="--force -h --help" + + if [[ "$cur" == -* ]]; then + COMPREPLY=($(compgen -W "$install_opts" -- "$cur")) + else + # Complete version targets + COMPREPLY=($(compgen -W "stable latest" -- "$cur")) + fi +} + +# Register the completion function +complete -F _claude_completions claude \ No newline at end of file diff --git a/shell-completions/claude-completions.fish b/shell-completions/claude-completions.fish new file mode 100644 index 0000000..758ad27 --- /dev/null +++ b/shell-completions/claude-completions.fish @@ -0,0 +1,91 @@ +# Fish shell completions for claude command + +# Global options +complete -c claude -s d -l debug -d "Enable debug mode" +complete -c claude -l verbose -d "Override verbose mode setting from config" +complete -c claude -s p -l print -d "Print response and exit (useful for pipes)" +complete -c claude -l output-format -xa "text json stream-json" -d "Output format (only works with --print)" +complete -c claude -l input-format -xa "text stream-json" -d "Input format (only works with --print)" +complete -c claude -l mcp-debug -d "[DEPRECATED] Enable MCP debug mode" +complete -c claude -l dangerously-skip-permissions -d "Bypass all permission checks" +complete -c claude -l allowedTools -d "Comma or space-separated list of tool names to allow" +complete -c claude -l disallowedTools -d "Comma or space-separated list of tool names to deny" +complete -c claude -l mcp-config -rF -d "Load MCP servers from a JSON file or string" +complete -c claude -l append-system-prompt -d "Append a system prompt to the default system prompt" +complete -c claude -l permission-mode -xa "acceptEdits bypassPermissions default plan" -d "Permission mode to use for the session" +complete -c claude -s c -l continue -d "Continue the most recent conversation" +complete -c claude -s r -l resume -d "Resume a conversation - provide a session ID or interactively select" +complete -c claude -l model -xa "sonnet opus haiku claude-sonnet-4-20250514" -d "Model for the current session" +complete -c claude -l fallback-model -xa "sonnet opus haiku claude-sonnet-4-20250514" -d "Enable automatic fallback to specified model when default model is overloaded" +complete -c claude -l settings -rF -d "Path to a settings JSON file to load additional settings from" +complete -c claude -l add-dir -rF -d "Additional directories to allow tool access to" +complete -c claude -l ide -d "Automatically connect to IDE on startup if exactly one valid IDE is available" +complete -c claude -l strict-mcp-config -d "Only use MCP servers from --mcp-config, ignoring all other MCP configurations" +complete -c claude -l session-id -d "Use a specific session ID for the conversation (must be a valid UUID)" +complete -c claude -s v -l version -d "Output the version number" +complete -c claude -s h -l help -d "Display help for command" + +# Main commands +complete -c claude -f -n "__fish_use_subcommand" -a "config" -d "Manage configuration" +complete -c claude -f -n "__fish_use_subcommand" -a "mcp" -d "Configure and manage MCP servers" +complete -c claude -f -n "__fish_use_subcommand" -a "migrate-installer" -d "Migrate from global npm installation to local installation" +complete -c claude -f -n "__fish_use_subcommand" -a "setup-token" -d "Set up a long-lived authentication token" +complete -c claude -f -n "__fish_use_subcommand" -a "doctor" -d "Check the health of your Claude Code auto-updater" +complete -c claude -f -n "__fish_use_subcommand" -a "update" -d "Check for updates and install if available" +complete -c claude -f -n "__fish_use_subcommand" -a "install" -d "Install Claude Code native build" + +# Config subcommands +complete -c claude -f -n "__fish_seen_subcommand_from config" -a "get" -d "Get a config value" +complete -c claude -f -n "__fish_seen_subcommand_from config" -a "set" -d "Set a config value" +complete -c claude -f -n "__fish_seen_subcommand_from config" -a "remove rm" -d "Remove a config value or items from a config array" +complete -c claude -f -n "__fish_seen_subcommand_from config" -a "list ls" -d "List all config values" +complete -c claude -f -n "__fish_seen_subcommand_from config" -a "add" -d "Add items to a config array" +complete -c claude -f -n "__fish_seen_subcommand_from config" -a "help" -d "Display help for command" + +# Config options +complete -c claude -s g -l global -n "__fish_seen_subcommand_from config" -d "Use global config" +complete -c claude -s h -l help -n "__fish_seen_subcommand_from config" -d "Display help for command" + +# MCP subcommands +complete -c claude -f -n "__fish_seen_subcommand_from mcp" -a "serve" -d "Start the Claude Code MCP server" +complete -c claude -f -n "__fish_seen_subcommand_from mcp" -a "add" -d "Add a server" +complete -c claude -f -n "__fish_seen_subcommand_from mcp" -a "remove" -d "Remove an MCP server" +complete -c claude -f -n "__fish_seen_subcommand_from mcp" -a "list" -d "List configured MCP servers" +complete -c claude -f -n "__fish_seen_subcommand_from mcp" -a "get" -d "Get details about an MCP server" +complete -c claude -f -n "__fish_seen_subcommand_from mcp" -a "add-json" -d "Add an MCP server (stdio or SSE) with a JSON string" +complete -c claude -f -n "__fish_seen_subcommand_from mcp" -a "add-from-claude-desktop" -d "Import MCP servers from Claude Desktop (Mac and WSL only)" +complete -c claude -f -n "__fish_seen_subcommand_from mcp" -a "reset-project-choices" -d "Reset all approved and rejected project-scoped (.mcp.json) servers within this project" +complete -c claude -f -n "__fish_seen_subcommand_from mcp" -a "help" -d "Display help for command" + +# MCP options +complete -c claude -s h -l help -n "__fish_seen_subcommand_from mcp" -d "Display help for command" + +# MCP serve options +complete -c claude -s p -l port -n "__fish_seen_subcommand_from mcp; and __fish_seen_subcommand_from serve" -d "Port number for MCP server" +complete -c claude -s h -l help -n "__fish_seen_subcommand_from mcp; and __fish_seen_subcommand_from serve" -d "Display help for command" + +# MCP add options +complete -c claude -s s -l scope -xa "local user project" -n "__fish_seen_subcommand_from mcp; and __fish_seen_subcommand_from add" -d "Configuration scope" +complete -c claude -s t -l transport -xa "stdio sse http" -n "__fish_seen_subcommand_from mcp; and __fish_seen_subcommand_from add" -d "Transport type" +complete -c claude -s e -l env -n "__fish_seen_subcommand_from mcp; and __fish_seen_subcommand_from add" -d "Set environment variables" +complete -c claude -s H -l header -n "__fish_seen_subcommand_from mcp; and __fish_seen_subcommand_from add" -d "Set HTTP headers for SSE and HTTP transports" +complete -c claude -s h -l help -n "__fish_seen_subcommand_from mcp; and __fish_seen_subcommand_from add" -d "Display help for command" + +# MCP add-json options +complete -c claude -s s -l scope -xa "local user project" -n "__fish_seen_subcommand_from mcp; and __fish_seen_subcommand_from add-json" -d "Configuration scope" +complete -c claude -s h -l help -n "__fish_seen_subcommand_from mcp; and __fish_seen_subcommand_from add-json" -d "Display help for command" + +# MCP add-from-claude-desktop options +complete -c claude -s s -l scope -xa "local user project" -n "__fish_seen_subcommand_from mcp; and __fish_seen_subcommand_from add-from-claude-desktop" -d "Configuration scope" +complete -c claude -s h -l help -n "__fish_seen_subcommand_from mcp; and __fish_seen_subcommand_from add-from-claude-desktop" -d "Display help for command" + +# Install options +complete -c claude -l force -n "__fish_seen_subcommand_from install" -d "Force installation even if already installed" +complete -c claude -s h -l help -n "__fish_seen_subcommand_from install" -d "Display help for command" + +# Install targets +complete -c claude -f -n "__fish_seen_subcommand_from install" -a "stable" -d "Install stable version" +complete -c claude -f -n "__fish_seen_subcommand_from install" -a "latest" -d "Install latest version" + +# Help options for simple commands +complete -c claude -s h -l help -n "__fish_seen_subcommand_from migrate-installer setup-token doctor update" -d "Display help for command" \ No newline at end of file diff --git a/shell-completions/claude-completions.zsh b/shell-completions/claude-completions.zsh new file mode 100644 index 0000000..011c993 --- /dev/null +++ b/shell-completions/claude-completions.zsh @@ -0,0 +1,213 @@ +#compdef claude + +# Zsh completion for claude command + +_claude() { + local context state state_descr line + typeset -A opt_args + + _arguments -C \ + '(-d --debug)'{-d,--debug}'[Enable debug mode]' \ + '--verbose[Override verbose mode setting from config]' \ + '(-p --print)'{-p,--print}'[Print response and exit (useful for pipes)]' \ + '--output-format[Output format]:format:(text json stream-json)' \ + '--input-format[Input format]:format:(text stream-json)' \ + '--mcp-debug[DEPRECATED - Enable MCP debug mode]' \ + '--dangerously-skip-permissions[Bypass all permission checks]' \ + '--allowedTools[Comma or space-separated list of tool names to allow]:tools:' \ + '--disallowedTools[Comma or space-separated list of tool names to deny]:tools:' \ + '--mcp-config[Load MCP servers from a JSON file or string]:file:_files' \ + '--append-system-prompt[Append a system prompt to the default system prompt]:prompt:' \ + '--permission-mode[Permission mode to use for the session]:mode:(acceptEdits bypassPermissions default plan)' \ + '(-c --continue)'{-c,--continue}'[Continue the most recent conversation]' \ + '(-r --resume)'{-r,--resume}'[Resume a conversation]:session_id:' \ + '--model[Model for the current session]:model:(sonnet opus haiku claude-sonnet-4-20250514)' \ + '--fallback-model[Enable automatic fallback to specified model]:model:(sonnet opus haiku claude-sonnet-4-20250514)' \ + '--settings[Path to a settings JSON file]:file:_files' \ + '--add-dir[Additional directories to allow tool access to]:directory:_directories' \ + '--ide[Automatically connect to IDE on startup]' \ + '--strict-mcp-config[Only use MCP servers from --mcp-config]' \ + '--session-id[Use a specific session ID (must be a valid UUID)]:uuid:' \ + '(-v --version)'{-v,--version}'[Output the version number]' \ + '(-h --help)'{-h,--help}'[Display help for command]' \ + '1: :_claude_commands' \ + '*::arg:->args' \ + && return 0 + + case $state in + args) + case $words[1] in + config) _claude_config ;; + mcp) _claude_mcp ;; + install) _claude_install ;; + migrate-installer|setup-token|doctor|update) + _arguments \ + '(-h --help)'{-h,--help}'[Display help for command]' + ;; + esac + ;; + esac +} + +_claude_commands() { + local commands; commands=( + 'config:Manage configuration' + 'mcp:Configure and manage MCP servers' + 'migrate-installer:Migrate from global npm installation to local installation' + 'setup-token:Set up a long-lived authentication token' + 'doctor:Check the health of your Claude Code auto-updater' + 'update:Check for updates and install if available' + 'install:Install Claude Code native build' + ) + _describe 'command' commands +} + +_claude_config() { + local context state state_descr line + typeset -A opt_args + + _arguments -C \ + '(-g --global)'{-g,--global}'[Use global config]' \ + '(-h --help)'{-h,--help}'[Display help for command]' \ + '1: :_claude_config_commands' \ + '*::arg:->args' \ + && return 0 + + case $state in + args) + case $words[1] in + get) + _arguments \ + '(-g --global)'{-g,--global}'[Use global config]' \ + '(-h --help)'{-h,--help}'[Display help for command]' \ + '1:key:' + ;; + set) + _arguments \ + '(-g --global)'{-g,--global}'[Use global config]' \ + '(-h --help)'{-h,--help}'[Display help for command]' \ + '1:key:' \ + '2:value:' + ;; + remove|rm) + _arguments \ + '(-g --global)'{-g,--global}'[Use global config]' \ + '(-h --help)'{-h,--help}'[Display help for command]' \ + '1:key:' \ + '*:values:' + ;; + list|ls) + _arguments \ + '(-g --global)'{-g,--global}'[Use global config]' \ + '(-h --help)'{-h,--help}'[Display help for command]' + ;; + add) + _arguments \ + '(-g --global)'{-g,--global}'[Use global config]' \ + '(-h --help)'{-h,--help}'[Display help for command]' \ + '1:key:' \ + '*:values:' + ;; + help) + _claude_config_commands + ;; + esac + ;; + esac +} + +_claude_config_commands() { + local commands; commands=( + 'get:Get a config value' + 'set:Set a config value' + 'remove:Remove a config value or items from a config array' + 'rm:Remove a config value or items from a config array' + 'list:List all config values' + 'ls:List all config values' + 'add:Add items to a config array' + 'help:Display help for command' + ) + _describe 'config command' commands +} + +_claude_mcp() { + local context state state_descr line + typeset -A opt_args + + _arguments -C \ + '(-h --help)'{-h,--help}'[Display help for command]' \ + '1: :_claude_mcp_commands' \ + '*::arg:->args' \ + && return 0 + + case $state in + args) + case $words[1] in + serve) + _arguments \ + '(-p --port)'{-p,--port}'[Port number for MCP server]:port:' \ + '(-h --help)'{-h,--help}'[Display help for command]' + ;; + add) + _arguments \ + '(-s --scope)'{-s,--scope}'[Configuration scope]:scope:(local user project)' \ + '(-t --transport)'{-t,--transport}'[Transport type]:transport:(stdio sse http)' \ + '(-e --env)'{-e,--env}'[Set environment variables]:env:' \ + '(-H --header)'{-H,--header}'[Set HTTP headers]:header:' \ + '(-h --help)'{-h,--help}'[Display help for command]' \ + '1:name:' \ + '2:commandOrUrl:' \ + '*:args:' + ;; + remove|get) + _arguments \ + '(-h --help)'{-h,--help}'[Display help for command]' \ + '1:name:' + ;; + add-json) + _arguments \ + '(-s --scope)'{-s,--scope}'[Configuration scope]:scope:(local user project)' \ + '(-h --help)'{-h,--help}'[Display help for command]' \ + '1:name:' \ + '2:json:' + ;; + add-from-claude-desktop) + _arguments \ + '(-s --scope)'{-s,--scope}'[Configuration scope]:scope:(local user project)' \ + '(-h --help)'{-h,--help}'[Display help for command]' + ;; + list|reset-project-choices) + _arguments \ + '(-h --help)'{-h,--help}'[Display help for command]' + ;; + help) + _claude_mcp_commands + ;; + esac + ;; + esac +} + +_claude_mcp_commands() { + local commands; commands=( + 'serve:Start the Claude Code MCP server' + 'add:Add a server' + 'remove:Remove an MCP server' + 'list:List configured MCP servers' + 'get:Get details about an MCP server' + 'add-json:Add an MCP server (stdio or SSE) with a JSON string' + 'add-from-claude-desktop:Import MCP servers from Claude Desktop (Mac and WSL only)' + 'reset-project-choices:Reset all approved and rejected project-scoped (.mcp.json) servers' + 'help:Display help for command' + ) + _describe 'mcp command' commands +} + +_claude_install() { + _arguments \ + '--force[Force installation even if already installed]' \ + '(-h --help)'{-h,--help}'[Display help for command]' \ + '1:target:(stable latest)' +} + +_claude "$@" \ No newline at end of file