Shell completions for Bash, Zsh #128#251
Conversation
…and init handler - Revert moss==1.0.0 back to moss>=1.0.0 to allow patch updates - Remove unnecessary RuntimeError handling for moss_core in init command - Remove unnecessary try/except around moss import in version command - Move _register_moss_commands to module level so app is fully populated for tests
…d lazy-loading - Set add_completion=False to avoid duplicate completion mechanisms (Typer built-in vs custom 'moss completions' command) - Add test_completions.py with 7 tests covering: - Bash/Zsh script output - Missing/invalid shell argument errors - SDK-dependent command registration (lazy-loading) - Help text display - Verification that --install-completion/--show-completion are removed Resolves PR usemoss#192 review comments.
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
@r4ghu @yatharthk2 can you review this pr |
|
@Sravan1011 can you update your PR for linting fixes? also please attach a 1 min mandatory video showing the working demo |
There was a problem hiding this comment.
Pull request overview
Adds a new moss completions CLI command intended to output Bash/Zsh completion scripts, and adjusts CLI command registration to separate SDK-dependent commands from SDK-independent ones.
Changes:
- Introduces
moss completions <bash|zsh>that prints shell completion scripts (including dynamic index-name completion viamoss index list --json). - Updates the CLI entrypoint to register
version,profile, andcompletionswithout importing SDK-dependent modules, and conditionally registers the rest. - Adds a new test module covering basic completions output and command registration behavior.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
| packages/moss-cli/src/moss_cli/main.py | Registers completions and refactors command registration to optionally skip SDK-dependent commands. |
| packages/moss-cli/src/moss_cli/commands/completions.py | Implements hard-coded Bash/Zsh completion scripts and the completions command. |
| packages/moss-cli/tests/test_completions.py | Adds tests for completions output, help behavior, and conditional command registration. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| from moss_cli.commands.completions import Shell, completions_command | ||
| from moss_cli.main import app |
| try: | ||
| _register_moss_commands() | ||
| except ImportError: | ||
| pass # moss SDK unavailable; SDK-dependent commands will be absent |
| esac | ||
| } | ||
|
|
||
| _moss |
| query) | ||
| case "$prev" in | ||
| --profile|--top-k|-k|--alpha|-a|--filter) ;; | ||
| *) COMPREPLY=($(compgen -W "$(_moss_index_names) --profile --top-k -k --alpha -a --filter --cloud -c --interactive -i" -- "$cur")) ;; | ||
| esac | ||
| ;; | ||
|
|
||
| completions) | ||
| COMPREPLY=($(compgen -W "bash zsh" -- "$cur")) | ||
| ;; |
| _moss_completions_cmd() { | ||
| local shells=('bash:Output bash completion script' 'zsh:Output zsh completion script') | ||
| _describe 'shell' shells | ||
| } |
| case $line[1] in | ||
| index) _moss_index ;; | ||
| doc) _moss_doc ;; | ||
| job) _moss_job ;; | ||
| profile) _moss_profile ;; | ||
| query) _moss_query ;; | ||
| completions) _moss_completions_cmd ;; | ||
| esac |
| app = typer.Typer( | ||
| name="moss", | ||
| help="Moss Semantic Search CLI", | ||
| add_completion=True, | ||
| add_completion=False, | ||
| no_args_is_help=True, | ||
| ) | ||
|
|
||
| # Register subgroups | ||
| app.add_typer(index_app, name="index", help="Manage indexes") | ||
| app.add_typer(doc_app, name="doc", help="Manage documents") | ||
| app.add_typer(job_app, name="job", help="Track background jobs") | ||
| # Register commands that do not depend on the moss SDK | ||
| app.command(name="version")(version_command) | ||
| app.command(name="completions")(completions_command) | ||
| app.add_typer(profile_app, name="profile", help="Manage auth profiles") |
| # eval "$(moss completions bash)" | ||
|
|
||
| _moss_index_names() { | ||
| moss index list --json 2>/dev/null | python3 -c " |
There was a problem hiding this comment.
🔴 _moss_index_names() uses wrong --json flag position, so index name completions always silently fail
The _moss_index_names() helper in both the bash and zsh completion scripts invokes moss index list --json, but --json is a group-level option defined on the top-level @app.callback() (packages/moss-cli/src/moss_cli/main.py:64). Click's MultiCommand has allow_interspersed_args=False, so group-level options must appear before the subcommand name. Running moss index list --json causes Click to pass --json down to the list command, which doesn't recognize it, resulting in "Error: No such option: --json" (exit code 2). Because the script redirects stderr to /dev/null and wraps the Python parser in try/except Exception: pass, this fails silently — the function returns nothing, and tab-completion for index names never works. The correct invocation is moss --json index list. This affects every completion that calls _moss_index_names: index get, index delete, doc add/delete/get, and query.
| moss index list --json 2>/dev/null | python3 -c " | |
| moss --json index list 2>/dev/null | python3 -c " |
Was this helpful? React with 👍 or 👎 to provide feedback.
|
|
||
| _moss_index_names() { | ||
| local -a names | ||
| names=(${(f)"$(moss index list --json 2>/dev/null | python3 -c ' |
There was a problem hiding this comment.
🔴 Zsh _moss_index_names() also uses wrong --json flag position
Same issue as the bash script: the zsh _moss_index_names() function calls moss index list --json but --json must precede the subcommand for Click to parse it as a group-level option. This silently fails because of 2>/dev/null and except Exception: pass, so zsh index name completions never return any results.
| names=(${(f)"$(moss index list --json 2>/dev/null | python3 -c ' | |
| names=(${(f)"$(moss --json index list 2>/dev/null | python3 -c ' |
Was this helpful? React with 👍 or 👎 to provide feedback.
| try: | ||
| _register_moss_commands() | ||
| except ImportError: | ||
| pass # moss SDK unavailable; SDK-dependent commands will be absent |
There was a problem hiding this comment.
🚩 Bare except ImportError may silently swallow SDK-present-but-broken import failures
The try/except ImportError block at packages/moss-cli/src/moss_cli/main.py:42-45 catches all ImportError exceptions, not just ModuleNotFoundError for the missing moss package. If the SDK is installed but its API changes (e.g., QueryOptions is removed from moss), then from moss import QueryOptions in search.py:13 would raise ImportError, and the entire set of SDK-dependent commands would silently disappear without any warning. Consider catching ModuleNotFoundError instead, or logging a warning when ImportError is caught but moss is importable.
Was this helpful? React with 👍 or 👎 to provide feedback.
This PR implements shell completions for the
mossCLI, addressing #128. It introduces a newmoss completionscommand group that generates native tab-completion scripts for Bash and Zsh, greatly improving command discoverability for power users.It also introduces dynamic index name completion, which queries the Moss API live during tab-completion so users can auto-complete their actual index names.
Fixes #128
Features Added
moss completions bash|zsh: Outputs valid shell completion scripts.moss completions install: Auto-detects the user's shell and safely installs the completion block to~/.bashrcor~/.zshrc.moss completions show: Prints the script for the current shell without installing.<TAB>aftermoss query,moss index get,moss index delete, or anymoss docsubcommand will fetch and list available index names using the configured credentials.Technical Details & Design Decisions
--install-completionflags (add_completion=Falseinitially, but reverted toTrueto preserve Click's env-var processing). We patch the generated Click scripts so theirinstruction_shellformat matches what Typer expects at runtime.complete_index_namecallback handles missing credentials and API errors by silently returning an empty list, ensuring tab-completion never errors out or blocks the user's terminal.test_completions.pycovering script generation, installation idempotency, and the dynamic completion callback behavior.Testing
pytest tests/(All 40 tests pass)