2929)
3030
3131
32- @marketplace_app .command ("update " )
33- def marketplace_update (
34- name : Optional [ str ] = typer .Argument (
35- None ,
36- help = "Marketplace name to update (updates all if not specified )" ,
32+ @marketplace_app .command ("add " )
33+ def marketplace_add (
34+ source : str = typer .Argument (
35+ ... ,
36+ help = "Marketplace source (URL, path, or GitHub repo )" ,
3737 ),
3838 app_type : str = typer .Option (
3939 "claude" ,
@@ -42,27 +42,133 @@ def marketplace_update(
4242 help = f"App type ({ ', ' .join (VALID_APP_TYPES )} )" ,
4343 ),
4444):
45- """Update installed marketplace(s) from their source.
45+ """Add a marketplace from a URL, path, or GitHub repo."""
46+ from code_assistant_manager .cli .option_utils import resolve_single_app
4647
47- This command updates installed marketplaces by pulling the latest changes
48- from their source repositories. If no name is specified, all marketplaces
49- are updated.
48+ app = resolve_single_app (app_type , VALID_APP_TYPES , default = "claude" )
49+ handler = get_handler (app )
5050
51- Examples:
52- cam plugin marketplace update # Update all marketplaces
53- cam plugin marketplace update my-marketplace # Update specific marketplace
51+ typer .echo (f"{ Colors .CYAN } Adding marketplace: { source } ...{ Colors .RESET } " )
52+ success , msg = handler .marketplace_add (source )
53+
54+ if success :
55+ typer .echo (f"{ Colors .GREEN } ✓ { msg } { Colors .RESET } " )
56+ else :
57+ typer .echo (f"{ Colors .RED } ✗ { msg } { Colors .RESET } " )
58+ raise typer .Exit (1 )
59+
60+
61+ @marketplace_app .command ("list" )
62+ def marketplace_list (
63+ app_type : str = typer .Option (
64+ "claude" ,
65+ "--app" ,
66+ "-a" ,
67+ help = f"App type ({ ', ' .join (VALID_APP_TYPES )} )" ,
68+ ),
69+ show_installed : bool = typer .Option (
70+ False ,
71+ "--installed" ,
72+ help = "Show only marketplaces installed in the app (not configured in CAM)" ,
73+ ),
74+ ):
75+ """List all configured marketplaces.
76+
77+ By default, shows marketplaces configured in CAM. Use --installed to show
78+ marketplaces actually installed in the target app.
5479 """
5580 from code_assistant_manager .cli .option_utils import resolve_single_app
81+ from code_assistant_manager .plugins import PluginManager
5682
5783 app = resolve_single_app (app_type , VALID_APP_TYPES , default = "claude" )
58- handler = get_handler (app )
5984
60- if name :
61- typer .echo (f"{ Colors .CYAN } Updating marketplace: { name } ...{ Colors .RESET } " )
85+ if show_installed :
86+ # Show marketplaces installed in the app
87+ handler = get_handler (app )
88+ success , output = handler .marketplace_list ()
89+ if success :
90+ typer .echo (output )
91+ else :
92+ typer .echo (f"{ Colors .RED } ✗ { output } { Colors .RESET } " )
93+ raise typer .Exit (1 )
6294 else :
63- typer .echo (f"{ Colors .CYAN } Updating all marketplaces...{ Colors .RESET } " )
95+ # Show CAM configured marketplaces
96+ manager = PluginManager ()
97+ all_repos = manager .get_all_repos ()
98+ configured_marketplaces = {
99+ k : v for k , v in all_repos .items () if v .type == "marketplace"
100+ }
101+
102+ if not configured_marketplaces :
103+ typer .echo (
104+ f"{ Colors .YELLOW } No marketplaces configured in CAM.{ Colors .RESET } "
105+ )
106+ typer .echo (
107+ f"Use 'cam plugin add-repo --type marketplace <owner>/<repo>' to add one."
108+ )
109+ return
110+
111+ typer .echo ("Configured marketplaces:" )
112+ typer .echo ()
113+
114+ for name , repo in sorted (configured_marketplaces .items ()):
115+ # Show status indicator
116+ status = (
117+ f"{ Colors .GREEN } ✓{ Colors .RESET } "
118+ if repo .enabled
119+ else f"{ Colors .RED } ✗{ Colors .RESET } "
120+ )
121+ typer .echo (f" { status } { name } " )
64122
65- success , msg = handler .marketplace_update (name )
123+ # Show aliases if any
124+ if hasattr (repo , "aliases" ) and repo .aliases :
125+ aliases_str = ", " .join (repo .aliases )
126+ typer .echo (f" Aliases: { aliases_str } " )
127+
128+ # Show description
129+ if repo .description :
130+ typer .echo (f" { repo .description } " )
131+
132+ # Show source
133+ if repo .repo_owner and repo .repo_name :
134+ source_url = (
135+ f"https://github.com/{ repo .repo_owner } /{ repo .repo_name } .git"
136+ )
137+ typer .echo (f" Source: Git ({ source_url } )" )
138+ else :
139+ typer .echo (
140+ f" Source: { Colors .YELLOW } No GitHub source configured{ Colors .RESET } "
141+ )
142+
143+ typer .echo ()
144+
145+
146+ @marketplace_app .command ("remove" )
147+ @marketplace_app .command ("rm" , hidden = True )
148+ def marketplace_remove (
149+ name : str = typer .Argument (
150+ ...,
151+ help = "Marketplace name to remove" ,
152+ ),
153+ force : bool = typer .Option (False , "--force" , "-f" , help = "Skip confirmation" ),
154+ app_type : str = typer .Option (
155+ "claude" ,
156+ "--app" ,
157+ "-a" ,
158+ help = f"App type ({ ', ' .join (VALID_APP_TYPES )} )" ,
159+ ),
160+ ):
161+ """Remove a configured marketplace."""
162+ from code_assistant_manager .cli .option_utils import resolve_single_app
163+
164+ app = resolve_single_app (app_type , VALID_APP_TYPES , default = "claude" )
165+ handler = get_handler (app )
166+
167+ if not force :
168+ typer .confirm (f"Remove marketplace '{ name } '?" , abort = True )
169+
170+ typer .echo (f"{ Colors .CYAN } Removing marketplace: { name } ...{ Colors .RESET } " )
171+ success , msg = handler .marketplace_remove (name )
66172
67173 if success :
68174 typer .echo (f"{ Colors .GREEN } ✓ { msg } { Colors .RESET } " )
@@ -71,6 +177,114 @@ def marketplace_update(
71177 raise typer .Exit (1 )
72178
73179
180+ @marketplace_app .command ("update" )
181+ def marketplace_update (
182+ name : Optional [str ] = typer .Argument (
183+ None ,
184+ help = "Marketplace name to update (updates all if not specified)" ,
185+ ),
186+ app_type : Optional [str ] = typer .Option (
187+ None ,
188+ "--app" ,
189+ "-a" ,
190+ help = f"App type to update marketplaces for ({ ', ' .join (VALID_APP_TYPES )} ). Updates all apps if not specified." ,
191+ ),
192+ ):
193+ """Update installed marketplace(s) from their source.
194+
195+ This command updates installed marketplaces by pulling the latest changes
196+ from their source repositories. If no name is specified, all marketplaces
197+ are updated. If no app is specified, marketplaces are updated for all apps.
198+
199+ Examples:
200+ cam plugin marketplace update # Update all marketplaces for all apps
201+ cam plugin marketplace update my-marketplace # Update specific marketplace for all apps
202+ cam plugin marketplace update --app claude # Update all marketplaces for Claude
203+ cam plugin marketplace update my-marketplace --app claude # Update specific marketplace for Claude
204+ """
205+ from code_assistant_manager .plugins import VALID_APP_TYPES , get_handler
206+
207+ if app_type :
208+ # Update for specific app
209+ if app_type not in VALID_APP_TYPES :
210+ typer .echo (
211+ f"{ Colors .RED } ✗ Invalid app type: { app_type } . Valid: { ', ' .join (VALID_APP_TYPES )} { Colors .RESET } "
212+ )
213+ raise typer .Exit (1 )
214+
215+ handler = get_handler (app_type )
216+
217+ if name :
218+ typer .echo (
219+ f"{ Colors .CYAN } Updating marketplace '{ name } ' for { app_type } ...{ Colors .RESET } "
220+ )
221+ else :
222+ typer .echo (
223+ f"{ Colors .CYAN } Updating all marketplaces for { app_type } ...{ Colors .RESET } "
224+ )
225+
226+ success , msg = handler .marketplace_update (name )
227+
228+ if success :
229+ typer .echo (f"{ Colors .GREEN } ✓ { msg } { Colors .RESET } " )
230+ else :
231+ typer .echo (f"{ Colors .RED } ✗ { msg } { Colors .RESET } " )
232+ raise typer .Exit (1 )
233+ else :
234+ # Update for all apps
235+ if name :
236+ typer .echo (
237+ f"{ Colors .CYAN } Updating marketplace '{ name } ' for all apps...{ Colors .RESET } "
238+ )
239+ else :
240+ typer .echo (
241+ f"{ Colors .CYAN } Updating all marketplaces for all apps...{ Colors .RESET } "
242+ )
243+
244+ all_success = True
245+ results = []
246+
247+ for current_app in VALID_APP_TYPES :
248+ try :
249+ handler = get_handler (current_app )
250+
251+ if name :
252+ typer .echo (
253+ f" { Colors .CYAN } Updating '{ name } ' for { current_app } ...{ Colors .RESET } "
254+ )
255+ else :
256+ typer .echo (
257+ f" { Colors .CYAN } Updating all marketplaces for { current_app } ...{ Colors .RESET } "
258+ )
259+
260+ success , msg = handler .marketplace_update (name )
261+
262+ if success :
263+ typer .echo (f" { Colors .GREEN } ✓ { current_app } : { msg } { Colors .RESET } " )
264+ results .append (f"{ current_app } : { msg } " )
265+ else :
266+ typer .echo (f" { Colors .RED } ✗ { current_app } : { msg } { Colors .RESET } " )
267+ results .append (f"{ current_app } : { msg } " )
268+ all_success = False
269+
270+ except Exception as e :
271+ error_msg = f"Failed to update { current_app } : { e } "
272+ typer .echo (f" { Colors .RED } ✗ { error_msg } { Colors .RESET } " )
273+ results .append (error_msg )
274+ all_success = False
275+
276+ if all_success :
277+ typer .echo (
278+ f"\n { Colors .GREEN } ✓ All marketplace updates completed successfully{ Colors .RESET } "
279+ )
280+ else :
281+ typer .echo (
282+ f"\n { Colors .YELLOW } ⚠ Some marketplace updates failed{ Colors .RESET } "
283+ )
284+ if not all_success :
285+ raise typer .Exit (1 )
286+
287+
74288# Add marketplace subcommand to plugin app
75289plugin_app .add_typer (marketplace_app , name = "marketplace" )
76290
0 commit comments