Feat/moss cli config profiles #126#143
Conversation
…oss#126) - add named profile storage and selection in config - support --profile and MOSS_PROFILE for credential resolution - add moss profile list command - keep backward compatibility with legacy flat config - add tests and docs for profile flows
There was a problem hiding this comment.
Pull request overview
Adds profile-aware credential/config handling to moss-cli to support switching between multiple projects without re-exporting credentials, including CLI surface area for selecting and listing profiles.
Changes:
- Introduces profile-based config normalization/resolution with legacy flat-config backward compatibility.
- Adds
--profilesupport across commands (plus a newmoss profile listcommand) and updatesmoss initto save credentials under a named profile. - Updates docs and adds tests for profile resolution, CLI behavior, and profile listing (also includes an interactive query mode addition).
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/moss-cli/src/moss_cli/config.py | Implements profile-aware config normalization, selection, and credential resolution. |
| packages/moss-cli/src/moss_cli/main.py | Adds global --profile option and registers the new profile command group. |
| packages/moss-cli/src/moss_cli/commands/profile.py | Adds moss profile list command with text/JSON output. |
| packages/moss-cli/src/moss_cli/commands/init_cmd.py | Extends moss init to save credentials under a selected profile. |
| packages/moss-cli/src/moss_cli/commands/index.py | Plumbs profile selection into index subcommands. |
| packages/moss-cli/src/moss_cli/commands/doc.py | Plumbs profile selection into doc subcommands. |
| packages/moss-cli/src/moss_cli/commands/job.py | Plumbs profile selection into job status command. |
| packages/moss-cli/src/moss_cli/commands/search.py | Adds profile option usage + introduces interactive query mode and /set parsing. |
| packages/moss-cli/tests/test_profiles.py | Adds tests for profile resolution, precedence, profile listing, and CLI integration. |
| packages/moss-cli/tests/test_search_set_command.py | Adds unit tests for interactive /set command parsing. |
| packages/moss-cli/README.md | Documents profile usage and adds examples (including interactive query mode). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| profile: Optional[str] = typer.Option( | ||
| None, "--profile", envvar="MOSS_PROFILE", help="Credential profile name" | ||
| ), |
There was a problem hiding this comment.
The subcommand-level --profile options also declare envvar="MOSS_PROFILE", while the global callback already reads MOSS_PROFILE/--profile into ctx.obj["profile"]. With Click/Typer, an envvar value is applied even when the flag is not present, so this can unintentionally override an explicit global --profile (e.g. moss --profile staging index list while MOSS_PROFILE=prod). To preserve the intended precedence (CLI > env), remove envvar from the subcommand --profile options, or only overwrite ctx.obj["profile"] when the option source is the command line (e.g. via ctx.get_parameter_source).
| if len(parts) != 3 or parts[0] != "/set": | ||
| return None, "Usage: /set <alpha|top-k> <value>" | ||
|
|
||
| key = parts[1].lower() | ||
| if key not in {"alpha", "top-k", "topk"}: | ||
| return None, "Unknown setting. Supported: alpha, top-k" |
There was a problem hiding this comment.
_parse_set_command accepts topk as an alias for top-k, but both the usage string (Usage: /set <alpha|top-k> <value>) and the unknown-setting message only mention top-k. This is an inconsistent user-facing error message; either include topk in the messages or drop the alias so the help text matches actual supported inputs.
| interactive: bool = typer.Option( | ||
| False, | ||
| "--interactive", | ||
| "-i", | ||
| help="Start interactive query session for multiple queries against one loaded index", | ||
| ), |
There was a problem hiding this comment.
This PR is described as adding config profiles (#126), but this change set also introduces a new interactive query mode (--interactive) and supporting /set commands. That’s a significant new user-facing feature; either update the PR description/linked issue scope accordingly or split interactive mode into a separate PR to keep review and release notes aligned.
| profile: Optional[str] = typer.Option( | ||
| None, "--profile", envvar="MOSS_PROFILE", help="Credential profile name" | ||
| ), |
There was a problem hiding this comment.
The subcommand-level --profile option declares envvar="MOSS_PROFILE" while the global callback already handles MOSS_PROFILE/--profile. Because Click/Typer applies envvar values even when the flag isn't present, this can override an explicit global --profile and lead to using credentials from an unexpected profile. Prefer removing envvar from subcommand --profile options (keeping it only on the global option) or only updating ctx.obj["profile"] when the option was passed on the command line.
| profile: Optional[str] = typer.Option( | ||
| None, "--profile", envvar="MOSS_PROFILE", help="Credential profile name" | ||
| ), |
There was a problem hiding this comment.
The subcommand-level --profile option declares envvar="MOSS_PROFILE" while the global callback already handles MOSS_PROFILE/--profile. In Click/Typer, envvar values are injected even when the flag isn't present, so this can override an explicit global --profile and select the wrong credentials. Remove envvar from subcommand --profile options (or only mutate ctx.obj["profile"] when the option source is the command line).
| profile: str | None = typer.Option( | ||
| None, "--profile", envvar="MOSS_PROFILE", help="Credential profile name" | ||
| ), |
There was a problem hiding this comment.
The --profile option here declares envvar="MOSS_PROFILE" even though the global callback already reads env/flags into ctx.obj["profile"]. Since Click/Typer applies envvar defaults even when the user didn't pass --profile, this can override an explicit global --profile and run against the wrong project. Prefer removing envvar from subcommand --profile options, or only overwriting ctx.obj["profile"] when --profile was explicitly passed.
| profile: Optional[str] = typer.Option( | ||
| None, | ||
| "--profile", | ||
| envvar="MOSS_PROFILE", | ||
| help="Profile name to save credentials under", | ||
| ), |
There was a problem hiding this comment.
moss init defines its own --profile with envvar="MOSS_PROFILE" even though the global callback already supports --profile/MOSS_PROFILE. If a user runs moss --profile staging init while MOSS_PROFILE=prod is set, Click/Typer will still populate this command option from the envvar (since the flag wasn’t passed after init), causing init to save credentials under prod instead of the explicitly requested global profile. To keep precedence consistent, remove envvar from this command option and rely on the global callback, or accept ctx here and read the already-resolved profile from ctx.obj when the option wasn’t explicitly passed.
| profile: Optional[str] = typer.Option( | ||
| None, "--profile", envvar="MOSS_PROFILE", help="Credential profile name" | ||
| ), |
There was a problem hiding this comment.
🔴 query command's --profile envvar overrides global --profile CLI flag
The query_command in search.py:53 declares envvar="MOSS_PROFILE" on its own --profile option, while the global callback in main.py:50 also reads from the same envvar. This is inconsistent with all other subcommands (index, doc, job, init) which do not set envvar on their subcommand-level --profile.
When MOSS_PROFILE=staging is set and the user runs moss --profile prod query my-index "test", the global callback correctly resolves profile="prod" (explicit flag overrides envvar) and sets ctx.obj["profile"] = "prod". However, the query command's own profile parameter falls back to the envvar (since no --profile was passed after query), receiving "staging". The if profile: guard at line 68 then overwrites ctx.obj["profile"] back to "staging", causing the wrong credentials to be used. The test test_global_profile_overrides_environment at packages/moss-cli/tests/test_profiles.py:176 validates this global-override behavior for index list but not for query, so the bug goes uncaught.
Was this helpful? React with 👍 or 👎 to provide feedback.
- preserve explicit global profile precedence by removing subcommand envvar defaults - make init honor the resolved global profile from ctx.obj - remove unrelated interactive query additions from this PR - clean up docs and tests to match the final scope
…ss#126) - stop set_profile_credentials from always switching active_profile - keep active profile unless missing or invalid - add tests for preserve/initialize active profile behavior
|
@yatharthk2 please check this PR ..if found any issuee then please tell |
|
@yatharthk2 please review this PR |
- add moss profile delete with confirmation and JSON output - preserve or safely recover the active profile when deleting - document the delete command and add regression tests
|
@yatharthk2 please review the pr |

I have read the CONTRIBUTING guide.
I have updated the documentation.
My code follows the style guidelines of this project.
I have performed a self-review of my own code.
I have added tests that prove my fix is effective or that my feature works.
New and existing unit tests pass locally with my changes.
Description-
Add config profiles to moss-cli for multi-project workflows.
This PR extends auth/config behavior to support named profiles so users can switch project context without re-exporting credentials each time.
What changed-
Added profile-aware config handling with backward compatibility for legacy flat config.
Added profile selection via command option and environment variable.
Extended init command to save credentials under a named profile.
Added profile listing command.
Updated docs and examples.
Added tests for profile resolution, precedence, CLI behavior, and profile listing.
Fixes-> #126
Type of Change-
New feature (non-breaking change which adds functionality)
This change requires a documentation update