@@ -841,6 +841,25 @@ def uninstall_prompt(
841841
842842 target_levels = resolve_level_targets (level , VALID_LEVELS , default = "user" )
843843
844+ # Collect all target files to uninstall
845+ all_targets = _collect_uninstall_targets (target_apps , target_levels , project_dir )
846+
847+ if not all_targets :
848+ typer .echo (f"{ Colors .YELLOW } No matching prompt files found{ Colors .RESET } " )
849+ return
850+
851+ # Confirm uninstallation unless force is specified
852+ if not force :
853+ _confirm_uninstall (all_targets )
854+
855+ # Perform the actual uninstallation
856+ _perform_uninstall (all_targets )
857+
858+
859+ def _collect_uninstall_targets (
860+ target_apps : List [str ], target_levels : List [str ], project_dir : Optional [Path ]
861+ ):
862+ """Collect all target files that need to be uninstalled."""
844863 targets = []
845864 copilot_targets = []
846865
@@ -861,35 +880,42 @@ def uninstall_prompt(
861880 continue
862881
863882 if app == "codebuddy" :
864- if lvl == "project" :
865- base_dir = lvl_project_dir or Path .cwd ()
866- codebuddy_path = base_dir / "CODEBUDDY.md"
867- agents_path = base_dir / "AGENTS.md"
868- # Prefer CODEBUDDY.md, but report AGENTS.md too
869- target = codebuddy_path if codebuddy_path .exists () else agents_path
870- if target .exists ():
871- targets .append (("codebuddy" , lvl , target , lvl_project_dir ))
872- elif lvl == "user" :
873- user_path = Path .home () / ".codebuddy" / "CODEBUDDY.md"
874- if user_path .exists ():
875- targets .append (("codebuddy" , lvl , user_path , None ))
883+ _collect_codebuddy_targets (app , lvl , lvl_project_dir , targets )
876884 continue
877885
878886 file_path = get_prompt_file_path (app , lvl , lvl_project_dir )
879- if not file_path :
880- continue
881- targets .append ((app , lvl , file_path , lvl_project_dir ))
882-
883- all_targets = targets + copilot_targets
887+ if file_path :
888+ targets .append ((app , lvl , file_path , lvl_project_dir ))
884889
885- if not all_targets :
886- typer .echo (f"{ Colors .YELLOW } No matching prompt files found{ Colors .RESET } " )
887- return
890+ return targets + copilot_targets
888891
889- if not force :
890- summary = ", " .join (f"{ app } :{ lvl } " for app , lvl , * _ in all_targets )
891- typer .confirm (f"Uninstall prompt files for { summary } ?" , abort = True )
892892
893+ def _collect_codebuddy_targets (
894+ app : str , lvl : str , lvl_project_dir : Optional [Path ], targets : List
895+ ):
896+ """Collect CodeBuddy target files for uninstallation."""
897+ if lvl == "project" :
898+ base_dir = lvl_project_dir or Path .cwd ()
899+ codebuddy_path = base_dir / "CODEBUDDY.md"
900+ agents_path = base_dir / "AGENTS.md"
901+ # Prefer CODEBUDDY.md, but report AGENTS.md too
902+ target = codebuddy_path if codebuddy_path .exists () else agents_path
903+ if target .exists ():
904+ targets .append (("codebuddy" , lvl , target , lvl_project_dir ))
905+ elif lvl == "user" :
906+ user_path = Path .home () / ".codebuddy" / "CODEBUDDY.md"
907+ if user_path .exists ():
908+ targets .append (("codebuddy" , lvl , user_path , None ))
909+
910+
911+ def _confirm_uninstall (all_targets ):
912+ """Show confirmation dialog for uninstallation."""
913+ summary = ", " .join (f"{ app } :{ lvl } " for app , lvl , * _ in all_targets )
914+ typer .confirm (f"Uninstall prompt files for { summary } ?" , abort = True )
915+
916+
917+ def _perform_uninstall (all_targets ):
918+ """Perform the actual file uninstallation."""
893919 for app , lvl , file_path , _ in all_targets :
894920 if not file_path .exists ():
895921 typer .echo (
@@ -955,7 +981,17 @@ def show_prompt_status(
955981 """Show prompt status for all apps."""
956982 manager = _get_prompt_manager ()
957983
958- # Show default prompt first
984+ # Show default prompt section
985+ _show_default_prompt_section (manager )
986+
987+ levels_to_show = resolve_level_targets (level , VALID_LEVELS , default = "all" )
988+
989+ for lvl in levels_to_show :
990+ _show_level_section (manager , lvl , project_dir )
991+
992+
993+ def _show_default_prompt_section (manager : PromptManager ):
994+ """Show the default prompt status section."""
959995 default_prompt = manager .get_default ()
960996 if default_prompt :
961997 typer .echo (f"\n { Colors .BOLD } Default Prompt:{ Colors .RESET } " )
@@ -966,122 +1002,135 @@ def show_prompt_status(
9661002 f"\n { Colors .BOLD } Default Prompt:{ Colors .RESET } { Colors .YELLOW } (none set){ Colors .RESET } "
9671003 )
9681004
969- levels_to_show = resolve_level_targets (level , VALID_LEVELS , default = "all" )
9701005
971- for lvl in levels_to_show :
972- typer .echo (
973- f"\n { Colors .BOLD } Prompt Status ({ lvl .capitalize ()} Level):{ Colors .RESET } \n "
974- )
1006+ def _show_level_section (manager : PromptManager , lvl : str , project_dir : Optional [Path ]):
1007+ """Show prompt status for a specific level."""
1008+ typer .echo (
1009+ f"\n { Colors .BOLD } Prompt Status ({ lvl .capitalize ()} Level):{ Colors .RESET } \n "
1010+ )
9751011
976- # Determine which apps to show for this level
977- apps_for_level = USER_LEVEL_APPS if lvl == "user" else VALID_APP_TYPES
1012+ # Determine which apps to show for this level
1013+ apps_for_level = USER_LEVEL_APPS if lvl == "user" else VALID_APP_TYPES
9781014
979- for app_type in apps_for_level :
980- # Handle Copilot specially
981- if app_type == "copilot" :
982- _show_copilot_status (manager , project_dir )
983- continue
1015+ for app_type in apps_for_level :
1016+ _show_app_status (manager , app_type , lvl , project_dir )
9841017
985- if app_type == "codebuddy" :
986- # Show CodeBuddy status for user or project level
987- if lvl == "user" :
988- file_path = Path .home () / ".codebuddy" / "CODEBUDDY.md"
989- try :
990- live_content = manager .get_live_content (
991- "codebuddy" , level = "user" , project_dir = None
992- )
993- except Exception :
994- live_content = None
995- else :
996- base_dir = project_dir or Path .cwd ()
997- codebuddy_file = base_dir / "CODEBUDDY.md"
998- agents_file = base_dir / "AGENTS.md"
999- file_path = (
1000- codebuddy_file if codebuddy_file .exists () else agents_file
1001- )
1002- try :
1003- live_content = manager .get_live_content (
1004- "codebuddy" , level = "project" , project_dir = project_dir
1005- )
1006- except Exception :
1007- live_content = None
1008-
1009- typer .echo (f"{ Colors .BOLD } CodeBuddy:{ Colors .RESET } " )
1010- typer .echo (f" { Colors .CYAN } File:{ Colors .RESET } { file_path } " )
10111018
1012- linked_prompt = None
1013- if live_content :
1014- for prompt_id , prompt in manager .get_all ().items ():
1015- if prompt .content .strip () == live_content .strip ():
1016- linked_prompt = prompt
1017- break
1019+ def _show_app_status (
1020+ manager : PromptManager , app_type : str , lvl : str , project_dir : Optional [Path ]
1021+ ):
1022+ """Show status for a specific app at a specific level."""
1023+ # Handle Copilot specially
1024+ if app_type == "copilot" :
1025+ _show_copilot_status (manager , project_dir )
1026+ return
10181027
1019- if linked_prompt :
1020- typer .echo (
1021- f" { Colors .BLUE } Linked Prompt:{ Colors .RESET } { linked_prompt .name } ({ linked_prompt .id } )"
1022- )
1028+ if app_type == "codebuddy" :
1029+ _show_codebuddy_status (manager , lvl , project_dir )
1030+ return
10231031
1024- if file_path .exists ():
1025- content = file_path .read_text (encoding = "utf-8" )
1026- if content .strip ():
1027- lines = content .strip ().split ("\n " )
1028- preview = (
1029- lines [0 ][:50 ] + "..." if len (lines [0 ]) > 50 else lines [0 ]
1030- )
1031- typer .echo (f" { Colors .GREEN } Content:{ Colors .RESET } { preview } " )
1032- typer .echo (f" { Colors .CYAN } Lines:{ Colors .RESET } { len (lines )} " )
1033- else :
1034- typer .echo (f" { Colors .YELLOW } Content:{ Colors .RESET } (empty)" )
1035- else :
1036- typer .echo (
1037- f" { Colors .YELLOW } Content:{ Colors .RESET } (file not found)"
1038- )
1032+ # Handle regular apps
1033+ _show_regular_app_status (manager , app_type , lvl , project_dir )
10391034
1040- typer .echo ()
1041- continue
10421035
1043- file_path = get_prompt_file_path (
1044- app_type , lvl , project_dir if lvl == "project" else None
1036+ def _show_codebuddy_status (
1037+ manager : PromptManager , lvl : str , project_dir : Optional [Path ]
1038+ ):
1039+ """Show CodeBuddy status for user or project level."""
1040+ if lvl == "user" :
1041+ file_path = Path .home () / ".codebuddy" / "CODEBUDDY.md"
1042+ try :
1043+ live_content = manager .get_live_content (
1044+ "codebuddy" , level = "user" , project_dir = None
10451045 )
1046+ except Exception :
1047+ live_content = None
1048+ else :
1049+ base_dir = project_dir or Path .cwd ()
1050+ codebuddy_file = base_dir / "CODEBUDDY.md"
1051+ agents_file = base_dir / "AGENTS.md"
1052+ file_path = codebuddy_file if codebuddy_file .exists () else agents_file
1053+ try :
1054+ live_content = manager .get_live_content (
1055+ "codebuddy" , level = "project" , project_dir = project_dir
1056+ )
1057+ except Exception :
1058+ live_content = None
10461059
1047- typer .echo (f"{ Colors .BOLD } { app_type . capitalize () } :{ Colors .RESET } " )
1048- typer .echo (f" { Colors .CYAN } File:{ Colors .RESET } { file_path } " )
1060+ typer .echo (f"{ Colors .BOLD } CodeBuddy :{ Colors .RESET } " )
1061+ typer .echo (f" { Colors .CYAN } File:{ Colors .RESET } { file_path } " )
10491062
1050- # Check which prompt is linked to this file
1051- linked_prompt = None
1052- try :
1053- live_content = manager .get_live_content (
1054- app_type ,
1055- level = lvl ,
1056- project_dir = project_dir if lvl == "project" else None ,
1057- )
1058- if live_content :
1059- # Find which stored prompt matches this content
1060- for prompt_id , prompt in manager .get_all ().items ():
1061- if prompt .content .strip () == live_content .strip ():
1062- linked_prompt = prompt
1063- break
1064- except Exception :
1065- pass
1063+ linked_prompt = None
1064+ if live_content :
1065+ for prompt_id , prompt in manager .get_all ().items ():
1066+ if prompt .content .strip () == live_content .strip ():
1067+ linked_prompt = prompt
1068+ break
10661069
1067- if linked_prompt :
1068- typer .echo (
1069- f" { Colors .BLUE } Linked Prompt:{ Colors .RESET } { linked_prompt .name } ({ linked_prompt .id } )"
1070- )
1070+ if linked_prompt :
1071+ typer .echo (
1072+ f" { Colors .BLUE } Linked Prompt:{ Colors .RESET } { linked_prompt .name } ({ linked_prompt .id } )"
1073+ )
10711074
1072- if file_path and file_path .exists ():
1073- content = file_path .read_text (encoding = "utf-8" )
1074- if content .strip ():
1075- lines = content .strip ().split ("\n " )
1076- preview = lines [0 ][:50 ] + "..." if len (lines [0 ]) > 50 else lines [0 ]
1077- typer .echo (f" { Colors .GREEN } Content:{ Colors .RESET } { preview } " )
1078- typer .echo (f" { Colors .CYAN } Lines:{ Colors .RESET } { len (lines )} " )
1079- else :
1080- typer .echo (f" { Colors .YELLOW } Content:{ Colors .RESET } (empty)" )
1081- else :
1082- typer .echo (f" { Colors .YELLOW } Content:{ Colors .RESET } (file not found)" )
1075+ if file_path .exists ():
1076+ content = file_path .read_text (encoding = "utf-8" )
1077+ if content .strip ():
1078+ lines = content .strip ().split ("\n " )
1079+ preview = lines [0 ][:50 ] + "..." if len (lines [0 ]) > 50 else lines [0 ]
1080+ typer .echo (f" { Colors .GREEN } Content:{ Colors .RESET } { preview } " )
1081+ typer .echo (f" { Colors .CYAN } Lines:{ Colors .RESET } { len (lines )} " )
1082+ else :
1083+ typer .echo (f" { Colors .YELLOW } Content:{ Colors .RESET } (empty)" )
1084+ else :
1085+ typer .echo (f" { Colors .YELLOW } Content:{ Colors .RESET } (file not found)" )
10831086
1084- typer .echo ()
1087+ typer .echo ()
1088+
1089+
1090+ def _show_regular_app_status (
1091+ manager : PromptManager , app_type : str , lvl : str , project_dir : Optional [Path ]
1092+ ):
1093+ """Show status for regular apps (non-copilot, non-codebuddy)."""
1094+ file_path = get_prompt_file_path (
1095+ app_type , lvl , project_dir if lvl == "project" else None
1096+ )
1097+
1098+ typer .echo (f"{ Colors .BOLD } { app_type .capitalize ()} :{ Colors .RESET } " )
1099+ typer .echo (f" { Colors .CYAN } File:{ Colors .RESET } { file_path } " )
1100+
1101+ # Check which prompt is linked to this file
1102+ linked_prompt = None
1103+ try :
1104+ live_content = manager .get_live_content (
1105+ app_type ,
1106+ level = lvl ,
1107+ project_dir = project_dir if lvl == "project" else None ,
1108+ )
1109+ if live_content :
1110+ # Find which stored prompt matches this content
1111+ for prompt_id , prompt in manager .get_all ().items ():
1112+ if prompt .content .strip () == live_content .strip ():
1113+ linked_prompt = prompt
1114+ break
1115+ except Exception :
1116+ pass
1117+
1118+ if linked_prompt :
1119+ typer .echo (
1120+ f" { Colors .BLUE } Linked Prompt:{ Colors .RESET } { linked_prompt .name } ({ linked_prompt .id } )"
1121+ )
1122+
1123+ if file_path and file_path .exists ():
1124+ content = file_path .read_text (encoding = "utf-8" )
1125+ if content .strip ():
1126+ lines = content .strip ().split ("\n " )
1127+ preview = lines [0 ][:50 ] + "..." if len (lines [0 ]) > 50 else lines [0 ]
1128+ typer .echo (f" { Colors .GREEN } Content:{ Colors .RESET } { preview } " )
1129+ typer .echo (f" { Colors .CYAN } Lines:{ Colors .RESET } { len (lines )} " )
1130+ else :
1131+ typer .echo (f" { Colors .YELLOW } Content:{ Colors .RESET } (empty)" )
1132+ else :
1133+ typer .echo (f" { Colors .YELLOW } Content:{ Colors .RESET } (file not found)" )
10851134
10861135
10871136def _show_copilot_status (manager : PromptManager , project_dir : Optional [Path ]):
0 commit comments