@@ -121,6 +121,15 @@ def parse_args() -> Namespace:
121121 "--effort" , type = str , help = "Effort level for optimization" , choices = ["low" , "medium" , "high" ], default = "medium"
122122 )
123123
124+ # Config management flags
125+ parser .add_argument (
126+ "--show-config" , action = "store_true" , help = "Show current or auto-detected configuration and exit."
127+ )
128+ parser .add_argument (
129+ "--reset-config" , action = "store_true" , help = "Remove codeflash configuration from project config file."
130+ )
131+ parser .add_argument ("-y" , "--yes" , action = "store_true" , help = "Skip confirmation prompts (useful for CI/scripts)." )
132+
124133 args , unknown_args = parser .parse_known_args ()
125134 sys .argv [:] = [sys .argv [0 ], * unknown_args ]
126135 return process_and_validate_cmd_args (args )
@@ -147,6 +156,16 @@ def process_and_validate_cmd_args(args: Namespace) -> Namespace:
147156 logger .info (f"Codeflash version { version } " )
148157 sys .exit ()
149158
159+ # Handle --show-config
160+ if getattr (args , "show_config" , False ):
161+ _handle_show_config ()
162+ sys .exit ()
163+
164+ # Handle --reset-config
165+ if getattr (args , "reset_config" , False ):
166+ _handle_reset_config (confirm = not getattr (args , "yes" , False ))
167+ sys .exit ()
168+
150169 if args .command == "vscode-install" :
151170 install_vscode_extension ()
152171 sys .exit ()
@@ -212,11 +231,22 @@ def process_pyproject_config(args: Namespace) -> Namespace:
212231 is_js_ts_project = pyproject_config .get ("language" ) in ("javascript" , "typescript" )
213232 if args .tests_root is None :
214233 if is_js_ts_project :
215- # Try common JS test directories, or default to module_root
234+ # Try common JS test directories at project root first
216235 for test_dir in ["test" , "tests" , "__tests__" ]:
217236 if Path (test_dir ).is_dir ():
218237 args .tests_root = test_dir
219238 break
239+ # If not found at project root, try inside module_root (e.g., src/test, src/__tests__)
240+ if args .tests_root is None and args .module_root :
241+ module_root_path = Path (args .module_root )
242+ for test_dir in ["test" , "tests" , "__tests__" ]:
243+ test_path = module_root_path / test_dir
244+ if test_path .is_dir ():
245+ args .tests_root = str (test_path )
246+ break
247+ # Final fallback: default to module_root
248+ # Note: This may cause issues if tests are colocated with source files
249+ # In such cases, the user should explicitly configure testsRoot in package.json
220250 if args .tests_root is None :
221251 args .tests_root = args .module_root
222252 else :
@@ -309,3 +339,91 @@ def handle_optimize_all_arg_parsing(args: Namespace) -> Namespace:
309339 else :
310340 args .all = Path (args .all ).resolve ()
311341 return args
342+
343+
344+ def _handle_show_config () -> None :
345+ """Show current or auto-detected Codeflash configuration."""
346+ from rich .table import Table
347+
348+ from codeflash .cli_cmds .console import console
349+ from codeflash .setup .detector import detect_project , has_existing_config
350+
351+ project_root = Path .cwd ()
352+ detected = detect_project (project_root )
353+
354+ # Check if config exists or is auto-detected
355+ config_exists = has_existing_config (project_root )
356+ status = "Saved config" if config_exists else "Auto-detected (not saved)"
357+
358+ console .print ()
359+ console .print (f"[bold]Codeflash Configuration[/bold] ({ status } )" )
360+ console .print ()
361+
362+ table = Table (show_header = True , header_style = "bold cyan" )
363+ table .add_column ("Setting" , style = "dim" )
364+ table .add_column ("Value" )
365+
366+ table .add_row ("Language" , detected .language )
367+ table .add_row ("Project root" , str (detected .project_root ))
368+ table .add_row ("Module root" , str (detected .module_root ))
369+ table .add_row ("Tests root" , str (detected .tests_root ) if detected .tests_root else "(not detected)" )
370+ table .add_row ("Test runner" , detected .test_runner or "(not detected)" )
371+ table .add_row ("Formatter" , ", " .join (detected .formatter_cmds ) if detected .formatter_cmds else "(not detected)" )
372+ table .add_row (
373+ "Ignore paths" , ", " .join (str (p ) for p in detected .ignore_paths ) if detected .ignore_paths else "(none)"
374+ )
375+ table .add_row ("Confidence" , f"{ detected .confidence :.0%} " )
376+
377+ console .print (table )
378+ console .print ()
379+
380+ if not config_exists :
381+ console .print ("[dim]Run [bold]codeflash --file <file>[/bold] to auto-save this config.[/dim]" )
382+
383+
384+ def _handle_reset_config (confirm : bool = True ) -> None :
385+ """Remove Codeflash configuration from project config file.
386+
387+ Args:
388+ confirm: If True, prompt for confirmation before removing.
389+
390+ """
391+ from codeflash .cli_cmds .console import console
392+ from codeflash .setup .config_writer import remove_config
393+ from codeflash .setup .detector import detect_project , has_existing_config
394+
395+ project_root = Path .cwd ()
396+
397+ if not has_existing_config (project_root ):
398+ console .print ("[yellow]No Codeflash configuration found to remove.[/yellow]" )
399+ return
400+
401+ detected = detect_project (project_root )
402+
403+ if confirm :
404+ console .print ("[bold]This will remove Codeflash configuration from your project.[/bold]" )
405+ console .print ()
406+
407+ config_file = "pyproject.toml" if detected .language == "python" else "package.json"
408+ console .print (f" Config file: { project_root / config_file } " )
409+ console .print ()
410+
411+ try :
412+ response = console .input ("[bold]Are you sure you want to remove the config? [y/N][/bold] " )
413+ except (EOFError , KeyboardInterrupt ):
414+ console .print ("\n [yellow]Cancelled.[/yellow]" )
415+ return
416+
417+ if response .lower () not in ("y" , "yes" ):
418+ console .print ("[yellow]Cancelled.[/yellow]" )
419+ return
420+
421+ success , message = remove_config (project_root , detected .language )
422+
423+ # Escape brackets in message to prevent Rich markup interpretation
424+ escaped_message = message .replace ("[" , "\\ [" )
425+
426+ if success :
427+ console .print (f"[green]✓[/green] { escaped_message } " )
428+ else :
429+ console .print (f"[red]✗[/red] { escaped_message } " )
0 commit comments