claude-mpm 5.4.14__py3-none-any.whl → 5.4.21__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +1 -1
  3. claude_mpm/agents/PM_INSTRUCTIONS.md +127 -21
  4. claude_mpm/cli/chrome_devtools_installer.py +175 -0
  5. claude_mpm/cli/commands/agents.py +0 -31
  6. claude_mpm/cli/commands/skills.py +193 -187
  7. claude_mpm/cli/parsers/agents_parser.py +0 -9
  8. claude_mpm/cli/parsers/auto_configure_parser.py +0 -138
  9. claude_mpm/cli/startup.py +237 -25
  10. claude_mpm/commands/mpm-config.md +1 -2
  11. claude_mpm/commands/mpm-help.md +14 -95
  12. claude_mpm/commands/mpm-organize.md +350 -153
  13. claude_mpm/hooks/claude_hooks/event_handlers.py +5 -0
  14. claude_mpm/scripts/start_activity_logging.py +0 -0
  15. claude_mpm/services/command_deployment_service.py +10 -0
  16. claude_mpm/services/skills/selective_skill_deployer.py +475 -1
  17. claude_mpm/services/skills_deployer.py +62 -6
  18. {claude_mpm-5.4.14.dist-info → claude_mpm-5.4.21.dist-info}/METADATA +1 -1
  19. {claude_mpm-5.4.14.dist-info → claude_mpm-5.4.21.dist-info}/RECORD +23 -28
  20. claude_mpm/cli/commands/agents_detect.py +0 -380
  21. claude_mpm/cli/commands/agents_recommend.py +0 -309
  22. claude_mpm/commands/mpm-agents-auto-configure.md +0 -278
  23. claude_mpm/commands/mpm-agents-detect.md +0 -177
  24. claude_mpm/commands/mpm-agents-list.md +0 -131
  25. claude_mpm/commands/mpm-agents-recommend.md +0 -223
  26. {claude_mpm-5.4.14.dist-info → claude_mpm-5.4.21.dist-info}/WHEEL +0 -0
  27. {claude_mpm-5.4.14.dist-info → claude_mpm-5.4.21.dist-info}/entry_points.txt +0 -0
  28. {claude_mpm-5.4.14.dist-info → claude_mpm-5.4.21.dist-info}/licenses/LICENSE +0 -0
  29. {claude_mpm-5.4.14.dist-info → claude_mpm-5.4.21.dist-info}/licenses/LICENSE-FAQ.md +0 -0
  30. {claude_mpm-5.4.14.dist-info → claude_mpm-5.4.21.dist-info}/top_level.txt +0 -0
@@ -972,23 +972,37 @@ class SkillsManagementCommand(BaseCommand):
972
972
  console.print(f"[red]Unexpected error: {e}[/red]")
973
973
 
974
974
  def _configure_skills(self, args) -> CommandResult:
975
- """Interactive skills configuration with checkbox selection.
975
+ """Interactive skills configuration using configuration.yaml.
976
976
 
977
977
  Provides checkbox-based selection interface matching agents configure UX:
978
- - Status column showing Installed/Available
979
- - Pre-selection for installed skills
980
- - Apply/Adjust/Cancel menu
981
- - While loop for adjustment
982
- - Simplified labels (checkbox state only)
983
-
984
- This is Option 3 (Hybrid approach): Separate command for interactive mode
985
- while keeping deploy-github for CLI automation.
978
+ - Shows current mode (user_defined vs agent_referenced)
979
+ - If agent mode: shows agent-scanned skills
980
+ - Allows switching to user_defined mode and selecting skills
981
+ - Can reset to agent mode (clears user_defined)
982
+ - Saves selections to configuration.yaml
983
+
984
+ Configuration structure:
985
+ ```yaml
986
+ skills:
987
+ agent_referenced: # Auto-populated from agent scan (read-only)
988
+ - systematic-debugging
989
+ - typescript-core
990
+ user_defined: # User override - if set, ONLY these are deployed
991
+ [] # Empty = use agent_referenced
992
+ ```
986
993
  """
987
994
  try:
995
+ from pathlib import Path
996
+
988
997
  import questionary
998
+ import yaml
989
999
  from questionary import Choice, Style
990
1000
  from rich.prompt import Prompt
991
1001
 
1002
+ from ...services.skills.selective_skill_deployer import (
1003
+ get_skills_to_deploy,
1004
+ )
1005
+
992
1006
  # Questionary style (matching agents configure)
993
1007
  QUESTIONARY_STYLE = Style(
994
1008
  [
@@ -1013,203 +1027,197 @@ class SkillsManagementCommand(BaseCommand):
1013
1027
  ]
1014
1028
  )
1015
1029
 
1016
- console.print("\n[bold cyan]Interactive Skills Configuration[/bold cyan]\n")
1017
- console.print(
1018
- "[dim]Select skills to install/uninstall using checkboxes[/dim]"
1019
- )
1020
- console.print("[dim]● = Installed, ○ = Available[/dim]\n")
1030
+ console.print("\n[bold cyan]Skills Configuration Manager[/bold cyan]\n")
1021
1031
 
1022
- # Get deployed skills for status detection
1023
- deployed_result = self.skills_deployer.check_deployed_skills()
1024
- deployed_skills = {
1025
- skill["name"] for skill in deployed_result.get("skills", [])
1026
- }
1032
+ # Load current configuration
1033
+ project_config_path = Path.cwd() / ".claude-mpm" / "configuration.yaml"
1034
+ skills_to_deploy, current_mode = get_skills_to_deploy(project_config_path)
1027
1035
 
1028
- # Get available skills from GitHub
1029
- console.print("[dim]Fetching available skills from GitHub...[/dim]\n")
1030
- available_result = self.skills_deployer.list_available_skills()
1036
+ # Display current mode and skill count
1037
+ console.print(f"[bold]Current Mode:[/bold] [cyan]{current_mode}[/cyan]")
1038
+ console.print(
1039
+ f"[bold]Active Skills:[/bold] {len(skills_to_deploy)} skills\n"
1040
+ )
1031
1041
 
1032
- if available_result.get("error"):
1033
- console.print(f"[red]Error: {available_result['error']}[/red]")
1034
- return CommandResult(
1035
- success=False, message=available_result["error"], exit_code=1
1042
+ if current_mode == "agent_referenced":
1043
+ console.print(
1044
+ "[dim]Agent mode: Skills are auto-detected from deployed agents[/dim]"
1045
+ )
1046
+ console.print(
1047
+ "[dim]Switch to user mode to manually select skills[/dim]\n"
1048
+ )
1049
+ else:
1050
+ console.print(
1051
+ "[dim]User mode: You've manually selected which skills to deploy[/dim]"
1036
1052
  )
1053
+ console.print("[dim]Reset to agent mode to use auto-detection[/dim]\n")
1054
+
1055
+ # Offer mode switching
1056
+ action_choices = [
1057
+ Choice("View current skills", value="view"),
1058
+ Choice("Switch to user mode (manual selection)", value="switch_user"),
1059
+ Choice("Reset to agent mode (auto-detection)", value="reset_agent"),
1060
+ Choice("Cancel", value="cancel"),
1061
+ ]
1062
+
1063
+ action = questionary.select(
1064
+ "What would you like to do?",
1065
+ choices=action_choices,
1066
+ style=QUESTIONARY_STYLE,
1067
+ ).ask()
1068
+
1069
+ if action == "cancel" or action is None:
1070
+ console.print("[yellow]Configuration cancelled[/yellow]")
1071
+ return CommandResult(success=True, exit_code=0)
1037
1072
 
1038
- # Flatten skills by category
1039
- all_skills = []
1040
- for category, skills in available_result.get("by_category", {}).items():
1041
- for skill in skills:
1042
- skill_info = {
1043
- "name": skill.get("name", "unknown"),
1044
- "category": category,
1045
- "is_deployed": skill.get("name", "unknown") in deployed_skills,
1046
- }
1047
- all_skills.append(skill_info)
1048
-
1049
- # Sort by deployed status (deployed first), then by name
1050
- all_skills.sort(key=lambda s: (not s["is_deployed"], s["name"]))
1051
-
1052
- # Build checkbox choices with pre-selection
1053
- # Loop to allow adjusting selection
1054
- while True:
1055
- skill_choices = []
1056
- skill_map = {} # For lookup after selection
1057
-
1058
- for skill in all_skills:
1059
- skill_name = skill["name"]
1060
- category = skill["category"]
1061
- is_deployed = skill["is_deployed"]
1062
-
1063
- # Simple format: "skill-name (category)"
1064
- # Checkbox state (checked/unchecked) indicates installed status
1065
- choice_text = f"{skill_name} ({category})"
1066
-
1067
- # Pre-select if deployed
1068
- choice = Choice(
1069
- title=choice_text, value=skill_name, checked=is_deployed
1070
- )
1073
+ if action == "view":
1074
+ # Display current skills
1075
+ console.print("\n[bold]Current Skills:[/bold]\n")
1076
+ for skill in sorted(skills_to_deploy):
1077
+ console.print(f" • {skill}")
1078
+ console.print()
1079
+ Prompt.ask("\nPress Enter to continue")
1080
+ return CommandResult(success=True, exit_code=0)
1071
1081
 
1072
- skill_choices.append(choice)
1073
- skill_map[skill_name] = skill
1082
+ if action == "reset_agent":
1083
+ # Reset to agent mode by clearing user_defined
1084
+ with open(project_config_path, encoding="utf-8") as f:
1085
+ config = yaml.safe_load(f) or {}
1074
1086
 
1075
- # Display checkbox selection
1076
- selected_skills = questionary.checkbox(
1077
- "Select skills (Space to toggle, Enter to confirm):",
1078
- choices=skill_choices,
1079
- style=QUESTIONARY_STYLE,
1080
- ).ask()
1087
+ if "skills" not in config:
1088
+ config["skills"] = {}
1081
1089
 
1082
- if selected_skills is None:
1083
- # User cancelled (Ctrl+C)
1084
- console.print("[yellow]Skills configuration cancelled[/yellow]")
1085
- return CommandResult(success=True, exit_code=0)
1090
+ config["skills"]["user_defined"] = []
1086
1091
 
1087
- # Determine changes
1088
- to_install = []
1089
- to_remove = []
1092
+ with open(project_config_path, "w", encoding="utf-8") as f:
1093
+ yaml.dump(config, f, default_flow_style=False, sort_keys=False)
1090
1094
 
1091
- for skill in all_skills:
1092
- skill_name = skill["name"]
1093
- is_deployed = skill["is_deployed"]
1094
- is_selected = skill_name in selected_skills
1095
+ console.print(
1096
+ "\n[green]✓ Reset to agent mode - skills will be auto-detected from agents[/green]\n"
1097
+ )
1098
+ Prompt.ask("\nPress Enter to continue")
1099
+ return CommandResult(success=True, exit_code=0)
1095
1100
 
1096
- if is_selected and not is_deployed:
1097
- to_install.append(skill_name)
1098
- elif not is_selected and is_deployed:
1099
- to_remove.append(skill_name)
1101
+ # Switch to user mode - manual skill selection
1102
+ if action == "switch_user":
1103
+ console.print(
1104
+ "\n[bold cyan]Switching to User Mode - Manual Skill Selection[/bold cyan]\n"
1105
+ )
1106
+ console.print("[dim]Fetching available skills from GitHub...[/dim]\n")
1100
1107
 
1101
- # Show summary of changes
1102
- console.print("\n[bold]Changes to apply:[/bold]")
1103
- if to_install:
1104
- console.print(
1105
- f"\n[green]✓ Install ({len(to_install)} skills):[/green]"
1106
- )
1107
- for skill in to_install:
1108
- console.print(f" • {skill}")
1108
+ # Get available skills
1109
+ available_result = self.skills_deployer.list_available_skills()
1109
1110
 
1110
- if to_remove:
1111
- console.print(
1112
- f"\n[yellow]✗ Remove ({len(to_remove)} skills):[/yellow]"
1111
+ if available_result.get("error"):
1112
+ console.print(f"[red]Error: {available_result['error']}[/red]")
1113
+ return CommandResult(
1114
+ success=False, message=available_result["error"], exit_code=1
1113
1115
  )
1114
- for skill in to_remove:
1115
- console.print(f" • {skill}")
1116
1116
 
1117
- if not to_install and not to_remove:
1118
- console.print(
1119
- "\n[dim]No changes (selection matches current deployment)[/dim]"
1120
- )
1117
+ # Flatten skills by category
1118
+ all_skills = []
1119
+ for category, skills in available_result.get("by_category", {}).items():
1120
+ for skill in skills:
1121
+ skill_name = skill.get("name", "unknown")
1122
+ is_currently_selected = skill_name in skills_to_deploy
1123
+ skill_info = {
1124
+ "name": skill_name,
1125
+ "category": category,
1126
+ "is_selected": is_currently_selected,
1127
+ }
1128
+ all_skills.append(skill_info)
1129
+
1130
+ # Sort by selection status (selected first), then by name
1131
+ all_skills.sort(key=lambda s: (not s["is_selected"], s["name"]))
1132
+
1133
+ # Build checkbox choices
1134
+ while True:
1135
+ skill_choices = []
1136
+
1137
+ for skill in all_skills:
1138
+ skill_name = skill["name"]
1139
+ category = skill["category"]
1140
+ is_selected = skill["is_selected"]
1141
+
1142
+ # Format: "skill-name (category)"
1143
+ choice_text = f"{skill_name} ({category})"
1144
+
1145
+ # Pre-select if currently in skills_to_deploy
1146
+ choice = Choice(
1147
+ title=choice_text, value=skill_name, checked=is_selected
1148
+ )
1121
1149
 
1122
- console.print()
1150
+ skill_choices.append(choice)
1151
+
1152
+ # Display checkbox selection
1153
+ selected_skills = questionary.checkbox(
1154
+ "Select skills (Space to toggle, Enter to confirm):",
1155
+ choices=skill_choices,
1156
+ style=QUESTIONARY_STYLE,
1157
+ ).ask()
1158
+
1159
+ if selected_skills is None:
1160
+ # User cancelled (Ctrl+C)
1161
+ console.print("[yellow]Skills configuration cancelled[/yellow]")
1162
+ return CommandResult(success=True, exit_code=0)
1163
+
1164
+ # Show summary
1165
+ console.print("\n[bold]Selected Skills:[/bold]")
1166
+ console.print(f" {len(selected_skills)} skills selected\n")
1167
+
1168
+ if selected_skills:
1169
+ for skill in sorted(selected_skills):
1170
+ console.print(f" • {skill}")
1171
+ console.print()
1172
+
1173
+ # Ask user to confirm, adjust, or cancel
1174
+ confirm_action = questionary.select(
1175
+ "\nWhat would you like to do?",
1176
+ choices=[
1177
+ Choice("Save to configuration", value="apply"),
1178
+ Choice("Adjust selection", value="adjust"),
1179
+ Choice("Cancel", value="cancel"),
1180
+ ],
1181
+ default="apply",
1182
+ style=QUESTIONARY_STYLE,
1183
+ ).ask()
1184
+
1185
+ if confirm_action == "cancel":
1186
+ console.print("[yellow]Configuration cancelled[/yellow]")
1187
+ Prompt.ask("\nPress Enter to continue")
1188
+ return CommandResult(success=True, exit_code=0)
1189
+
1190
+ if confirm_action == "adjust":
1191
+ # Update selection state and loop back
1192
+ for skill in all_skills:
1193
+ skill["is_selected"] = skill["name"] in selected_skills
1194
+ console.print("\n[dim]Adjusting selection...[/dim]\n")
1195
+ continue
1196
+
1197
+ # Save to configuration.yaml
1198
+ with open(project_config_path, encoding="utf-8") as f:
1199
+ config = yaml.safe_load(f) or {}
1200
+
1201
+ if "skills" not in config:
1202
+ config["skills"] = {}
1203
+
1204
+ config["skills"]["user_defined"] = sorted(selected_skills)
1205
+
1206
+ with open(project_config_path, "w", encoding="utf-8") as f:
1207
+ yaml.dump(config, f, default_flow_style=False, sort_keys=False)
1123
1208
 
1124
- # Ask user to confirm, adjust, or cancel
1125
- action = questionary.select(
1126
- "\nWhat would you like to do?",
1127
- choices=[
1128
- Choice("Apply these changes", value="apply"),
1129
- Choice("Adjust selection", value="adjust"),
1130
- Choice("Cancel", value="cancel"),
1131
- ],
1132
- default="apply",
1133
- style=QUESTIONARY_STYLE,
1134
- ).ask()
1135
-
1136
- if action == "cancel":
1137
- console.print("[yellow]Changes cancelled[/yellow]")
1138
- Prompt.ask("\nPress Enter to continue")
1139
- return CommandResult(success=True, exit_code=0)
1140
- if action == "adjust":
1141
- # Loop back to skill selection
1142
- console.print("\n[dim]Adjusting selection...[/dim]\n")
1143
- continue
1144
-
1145
- # Apply changes
1146
- success = True
1147
- errors = []
1148
-
1149
- # Install skills
1150
- if to_install:
1151
- console.print("\n[bold cyan]Installing skills...[/bold cyan]\n")
1152
- for skill_name in to_install:
1153
- try:
1154
- # Deploy single skill
1155
- result = self.skills_deployer.deploy_skills(
1156
- skill_names=[skill_name], force=False
1157
- )
1158
-
1159
- if result.get("errors"):
1160
- errors.extend(result["errors"])
1161
- success = False
1162
- else:
1163
- console.print(
1164
- f"[green]✓ Installed: {skill_name}[/green]"
1165
- )
1166
- except Exception as e:
1167
- errors.append(f"Failed to install {skill_name}: {e}")
1168
- success = False
1169
-
1170
- # Remove skills
1171
- if to_remove:
1172
- console.print("\n[bold yellow]Removing skills...[/bold yellow]\n")
1173
- for skill_name in to_remove:
1174
- try:
1175
- # Remove single skill
1176
- result = self.skills_deployer.remove_skills(
1177
- skill_names=[skill_name]
1178
- )
1179
-
1180
- if result.get("errors"):
1181
- errors.extend(result["errors"])
1182
- success = False
1183
- else:
1184
- console.print(
1185
- f"[yellow]✗ Removed: {skill_name}[/yellow]"
1186
- )
1187
- except Exception as e:
1188
- errors.append(f"Failed to remove {skill_name}: {e}")
1189
- success = False
1190
-
1191
- # Show errors if any
1192
- if errors:
1193
- console.print(f"\n[red]✗ {len(errors)} error(s):[/red]")
1194
- for error in errors:
1195
- console.print(f" • {error}")
1196
-
1197
- # Show restart instructions
1198
- if success and (to_install or to_remove):
1199
1209
  console.print(
1200
- "\n[bold green]✓ Changes applied successfully![/bold green]"
1210
+ f"\n[green]✓ Saved {len(selected_skills)} skills to user_defined mode[/green]"
1201
1211
  )
1202
- console.print("\n[yellow]⚠️ Important:[/yellow]")
1203
- console.print(" Restart Claude Code for changes to take effect")
1204
-
1205
- console.print()
1206
- Prompt.ask("\nPress Enter to continue")
1212
+ console.print(
1213
+ "[yellow]⚠️ Important:[/yellow] Run [cyan]claude-mpm init[/cyan] to deploy these skills\n"
1214
+ )
1215
+ Prompt.ask("\nPress Enter to continue")
1207
1216
 
1208
- # Exit the loop after successful execution
1209
- break
1217
+ # Exit the loop after successful save
1218
+ break
1210
1219
 
1211
- exit_code = 0 if success else 1
1212
- return CommandResult(success=success, exit_code=exit_code)
1220
+ return CommandResult(success=True, exit_code=0)
1213
1221
 
1214
1222
  except Exception as e:
1215
1223
  console.print(f"[red]Error in skills configuration: {e}[/red]")
@@ -1218,8 +1226,6 @@ class SkillsManagementCommand(BaseCommand):
1218
1226
  console.print(f"[dim]{traceback.format_exc()}[/dim]")
1219
1227
  return CommandResult(success=False, message=str(e), exit_code=1)
1220
1228
 
1221
- return CommandResult(success=False, message=str(e), exit_code=1)
1222
-
1223
1229
 
1224
1230
  def manage_skills(args) -> int:
1225
1231
  """
@@ -406,15 +406,6 @@ Available commands:
406
406
  help="Show descriptions and metadata for each agent",
407
407
  )
408
408
 
409
- # Auto-configuration commands (TSK-0054 Phase 5)
410
- from .auto_configure_parser import (
411
- add_agents_detect_subparser,
412
- add_agents_recommend_subparser,
413
- )
414
-
415
- add_agents_detect_subparser(agents_subparsers)
416
- add_agents_recommend_subparser(agents_subparsers)
417
-
418
409
  # Phase 3: Agent Selection Modes (single-tier deployment)
419
410
  # Minimal configuration - deploy 6 core agents
420
411
  deploy_minimal_parser = agents_subparsers.add_parser(
@@ -118,141 +118,3 @@ Examples:
118
118
  )
119
119
 
120
120
  return auto_configure_parser
121
-
122
-
123
- def add_agents_detect_subparser(agents_subparsers) -> argparse.ArgumentParser:
124
- """
125
- Add the agents detect subparser for toolchain detection.
126
-
127
- WHY: Allows users to see what toolchain is detected without making changes,
128
- useful for debugging and verification.
129
-
130
- Args:
131
- agents_subparsers: The agents subparsers object
132
-
133
- Returns:
134
- The configured detect subparser
135
- """
136
- detect_parser = agents_subparsers.add_parser(
137
- "detect",
138
- help="Detect project toolchain without deploying",
139
- description="""
140
- Detect and display project toolchain without making any changes.
141
-
142
- This command analyzes your project to detect:
143
- • Programming languages and versions
144
- • Frameworks and libraries
145
- • Deployment targets and platforms
146
-
147
- Useful for debugging toolchain detection and verifying what would be
148
- detected before running auto-configure.
149
- """,
150
- formatter_class=argparse.RawDescriptionHelpFormatter,
151
- epilog="""
152
- Examples:
153
- # Detect toolchain in current directory
154
- claude-mpm agents detect
155
-
156
- # Detect with verbose output showing evidence
157
- claude-mpm agents detect --verbose
158
-
159
- # JSON output for scripting
160
- claude-mpm agents detect --json
161
-
162
- # Detect specific project
163
- claude-mpm agents detect --project-path /path/to/project
164
- """,
165
- )
166
- add_common_arguments(detect_parser)
167
-
168
- detect_parser.add_argument(
169
- "--project-path",
170
- type=Path,
171
- metavar="PATH",
172
- help="Project path to analyze (default: current directory)",
173
- )
174
-
175
- return detect_parser
176
-
177
-
178
- def add_agents_recommend_subparser(
179
- agents_subparsers,
180
- ) -> argparse.ArgumentParser:
181
- """
182
- Add the agents recommend subparser for agent recommendations.
183
-
184
- WHY: Allows users to see what agents would be recommended without deploying,
185
- useful for reviewing recommendations before committing to deployment.
186
-
187
- Args:
188
- agents_subparsers: The agents subparsers object
189
-
190
- Returns:
191
- The configured recommend subparser
192
- """
193
- recommend_parser = agents_subparsers.add_parser(
194
- "recommend",
195
- help="Show recommended agents without deploying",
196
- description="""
197
- Show recommended agents based on project toolchain without deploying.
198
-
199
- This command analyzes your project toolchain and recommends appropriate
200
- agents with detailed reasoning for each recommendation. No changes are
201
- made to your project.
202
-
203
- Useful for:
204
- • Reviewing recommendations before deployment
205
- • Understanding why agents are recommended
206
- • Adjusting confidence thresholds
207
- """,
208
- formatter_class=argparse.RawDescriptionHelpFormatter,
209
- epilog="""
210
- Examples:
211
- # Show recommendations with reasoning
212
- claude-mpm agents recommend
213
-
214
- # Require 90% confidence for recommendations
215
- claude-mpm agents recommend --min-confidence 0.9
216
-
217
- # JSON output for scripting
218
- claude-mpm agents recommend --json
219
-
220
- # Hide detailed reasoning
221
- claude-mpm agents recommend --no-reasoning
222
-
223
- # Recommend for specific project
224
- claude-mpm agents recommend --project-path /path/to/project
225
- """,
226
- )
227
- add_common_arguments(recommend_parser)
228
-
229
- recommend_parser.add_argument(
230
- "--project-path",
231
- type=Path,
232
- metavar="PATH",
233
- help="Project path to analyze (default: current directory)",
234
- )
235
-
236
- recommend_parser.add_argument(
237
- "--min-confidence",
238
- type=float,
239
- default=0.8,
240
- metavar="FLOAT",
241
- help="Minimum confidence threshold for recommendations (0.0-1.0, default: 0.8)",
242
- )
243
-
244
- recommend_parser.add_argument(
245
- "--show-reasoning",
246
- action="store_true",
247
- default=True,
248
- help="Show detailed reasoning for recommendations (default)",
249
- )
250
-
251
- recommend_parser.add_argument(
252
- "--no-reasoning",
253
- dest="show_reasoning",
254
- action="store_false",
255
- help="Hide detailed reasoning for recommendations",
256
- )
257
-
258
- return recommend_parser