Skip to content

Commit 8a4a36f

Browse files
zhujian0805claude
andcommitted
feat: comprehensive marketplace management and CLI improvements
- Add --all option to marketplace install command for bulk installation - Add new uninstall command for marketplaces with --all support - Fix inconsistent output formatting in marketplace list commands across all app handlers - Standardize marketplace list output to use numbered lists with ✓ indicators - Fix import errors in server_config tests by adding missing wrapper functions - Add new prompt management CLI commands (prompt_crud, prompt_defaults, etc.) - Refactor and improve codebase health across multiple modules - Enhance error handling and user feedback in CLI commands 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 7047dca commit 8a4a36f

34 files changed

+1926
-1644
lines changed

code_assistant_manager/agents/base.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,11 @@ def __init__(
4040
@abstractmethod
4141
def app_name(self) -> str:
4242
"""Return the name of the app (e.g., 'claude')."""
43-
pass
4443

4544
@property
4645
@abstractmethod
4746
def _default_agents_dir(self) -> Path:
4847
"""Return the default agents directory for this app."""
49-
pass
5048

5149
@property
5250
def agents_dir(self) -> Path:

code_assistant_manager/cli/agents_commands.py

Lines changed: 62 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,56 @@
11
"""CLI commands for agent management."""
22

33
import logging
4-
from pathlib import Path
54
from typing import Optional
65

76
import typer
87

9-
from code_assistant_manager.agents import (
10-
VALID_APP_TYPES,
11-
Agent,
12-
AgentManager,
13-
AgentRepo,
14-
)
8+
from code_assistant_manager.agents import VALID_APP_TYPES, AgentManager, AgentRepo
159
from code_assistant_manager.cli.option_utils import resolve_app_targets
1610
from code_assistant_manager.menu.base import Colors
11+
12+
# Module-level variables for typer defaults to avoid B008 violations
13+
URL_ARGUMENT = typer.Argument(
14+
None,
15+
help="GitHub URL or owner/repo to fetch and save (e.g., https://github.com/owner/repo or owner/repo)",
16+
)
17+
SAVE_OPTION = typer.Option(
18+
False,
19+
"--save",
20+
"-s",
21+
help="Save the fetched repo to config (only used with URL argument)",
22+
)
23+
AGENTS_PATH_OPTION = typer.Option(
24+
None,
25+
"--agents-path",
26+
help="Agents subdirectory path in the repo (only used with URL argument)",
27+
)
28+
AGENT_KEY_ARGUMENT = typer.Argument(..., help="Agent identifier")
29+
APP_TYPE_OPTION = typer.Option(
30+
"claude",
31+
"--app",
32+
"-a",
33+
help="App type(s) to install to (claude, codex, gemini, droid, codebuddy, all). Comma-separated.",
34+
)
35+
FORCE_OPTION = typer.Option(False, "--force", "-f", help="Skip confirmation")
36+
OWNER_OPTION = typer.Option(..., "--owner", "-o", help="Repository owner")
37+
NAME_OPTION = typer.Option(..., "--name", "-n", help="Repository name")
38+
BRANCH_OPTION = typer.Option("main", "--branch", "-b", help="Repository branch")
39+
AGENTS_PATH_OPTION_REPO = typer.Option(
40+
None, "--agents-path", help="Agents subdirectory path"
41+
)
42+
APP_TYPE_OPTION_ALL = typer.Option(
43+
None,
44+
"--app",
45+
"-a",
46+
help="App type(s) to show (claude, codex, gemini, droid, codebuddy, all). Default shows all.",
47+
)
48+
APP_TYPE_OPTION_UNINSTALL = typer.Option(
49+
...,
50+
"--app",
51+
"-a",
52+
help="App type(s) to uninstall all agents from (claude, codex, gemini, droid, codebuddy, all). Comma-separated.",
53+
)
1754
from code_assistant_manager.plugins.fetch import parse_github_url
1855

1956
logger = logging.getLogger(__name__)
@@ -67,21 +104,9 @@ def list_agents():
67104

68105
@agent_app.command("fetch")
69106
def fetch_agents(
70-
url: Optional[str] = typer.Argument(
71-
None,
72-
help="GitHub URL or owner/repo to fetch and save (e.g., https://github.com/owner/repo or owner/repo)",
73-
),
74-
save: bool = typer.Option(
75-
False,
76-
"--save",
77-
"-s",
78-
help="Save the fetched repo to config (only used with URL argument)",
79-
),
80-
agents_path: Optional[str] = typer.Option(
81-
None,
82-
"--agents-path",
83-
help="Agents subdirectory path in the repo (only used with URL argument)",
84-
),
107+
url: Optional[str] = URL_ARGUMENT,
108+
save: bool = SAVE_OPTION,
109+
agents_path: Optional[str] = AGENTS_PATH_OPTION,
85110
):
86111
"""Fetch agents from configured repositories or a specific GitHub URL.
87112
@@ -227,13 +252,8 @@ def view_agent(agent_key: str):
227252

228253
@agent_app.command("install")
229254
def install_agent(
230-
agent_key: str = typer.Argument(..., help="Agent identifier"),
231-
app_type: str = typer.Option(
232-
"claude",
233-
"--app",
234-
"-a",
235-
help="App type(s) to install to (claude, codex, gemini, droid, codebuddy, all). Comma-separated.",
236-
),
255+
agent_key: str = AGENT_KEY_ARGUMENT,
256+
app_type: str = APP_TYPE_OPTION,
237257
):
238258
"""Install an agent to one or more app's agents directories."""
239259
target_apps = resolve_app_targets(app_type, VALID_APP_TYPES, default="claude")
@@ -255,14 +275,9 @@ def install_agent(
255275

256276
@agent_app.command("uninstall")
257277
def uninstall_agent(
258-
agent_key: str = typer.Argument(..., help="Agent identifier"),
259-
app_type: str = typer.Option(
260-
"claude",
261-
"--app",
262-
"-a",
263-
help="App type(s) to uninstall from (claude, codex, gemini, droid, codebuddy, all). Comma-separated.",
264-
),
265-
force: bool = typer.Option(False, "--force", "-f", help="Skip confirmation"),
278+
agent_key: str = AGENT_KEY_ARGUMENT,
279+
app_type: str = APP_TYPE_OPTION,
280+
force: bool = FORCE_OPTION,
266281
):
267282
"""Uninstall an agent from one or more app's agents directories."""
268283
target_apps = resolve_app_targets(app_type, VALID_APP_TYPES, default="claude")
@@ -316,12 +331,10 @@ def list_repos():
316331

317332
@agent_app.command("add-repo")
318333
def add_repo(
319-
owner: str = typer.Option(..., "--owner", "-o", help="Repository owner"),
320-
name: str = typer.Option(..., "--name", "-n", help="Repository name"),
321-
branch: str = typer.Option("main", "--branch", "-b", help="Repository branch"),
322-
agents_path: Optional[str] = typer.Option(
323-
None, "--agents-path", help="Agents subdirectory path"
324-
),
334+
owner: str = OWNER_OPTION,
335+
name: str = NAME_OPTION,
336+
branch: str = BRANCH_OPTION,
337+
agents_path: Optional[str] = AGENTS_PATH_OPTION_REPO,
325338
):
326339
"""Add an agent repository."""
327340
manager = _get_agent_manager()
@@ -343,9 +356,9 @@ def add_repo(
343356

344357
@agent_app.command("remove-repo")
345358
def remove_repo(
346-
owner: str = typer.Option(..., "--owner", "-o", help="Repository owner"),
347-
name: str = typer.Option(..., "--name", "-n", help="Repository name"),
348-
force: bool = typer.Option(False, "--force", "-f", help="Skip confirmation"),
359+
owner: str = OWNER_OPTION,
360+
name: str = NAME_OPTION,
361+
force: bool = FORCE_OPTION,
349362
):
350363
"""Remove an agent repository."""
351364
manager = _get_agent_manager()
@@ -363,12 +376,7 @@ def remove_repo(
363376

364377
@agent_app.command("installed")
365378
def list_installed_agents(
366-
app_type: Optional[str] = typer.Option(
367-
None,
368-
"--app",
369-
"-a",
370-
help="App type(s) to show (claude, codex, gemini, droid, codebuddy, all). Default shows all.",
371-
),
379+
app_type: Optional[str] = APP_TYPE_OPTION_ALL,
372380
):
373381
"""Show installed agents for each app."""
374382
manager = _get_agent_manager()
@@ -420,13 +428,8 @@ def list_installed_agents(
420428

421429
@agent_app.command("uninstall-all")
422430
def uninstall_all_agents(
423-
app_type: str = typer.Option(
424-
...,
425-
"--app",
426-
"-a",
427-
help="App type(s) to uninstall all agents from (claude, codex, gemini, droid, codebuddy, all). Comma-separated.",
428-
),
429-
force: bool = typer.Option(False, "--force", "-f", help="Skip confirmation"),
431+
app_type: str = APP_TYPE_OPTION_UNINSTALL,
432+
force: bool = FORCE_OPTION,
430433
):
431434
"""Uninstall all agents from one or more apps."""
432435
target_apps = resolve_app_targets(app_type, VALID_APP_TYPES)

code_assistant_manager/cli/base_commands.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import logging
88
from abc import ABC, abstractmethod
9-
from typing import Any, Dict, List, Optional, Tuple, Union
9+
from typing import Any, List, Optional, Tuple
1010

1111
import typer
1212

@@ -84,7 +84,6 @@ def confirm_action(self, message: str, default: bool = False) -> bool:
8484
@abstractmethod
8585
def execute(self, *args, **kwargs) -> int:
8686
"""Execute the command. Must be implemented by subclasses."""
87-
pass
8887

8988

9089
class AppAwareCommand(BaseCommand):

code_assistant_manager/cli/plugins/plugin_discovery_commands.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
from code_assistant_manager.plugins import (
1313
VALID_APP_TYPES,
1414
PluginManager,
15-
fetch_repo_info_from_url,
1615
get_handler,
1716
parse_github_url,
1817
)

code_assistant_manager/cli/plugins/plugin_helpers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import logging
77

8-
from code_assistant_manager.plugins import VALID_APP_TYPES, get_handler
8+
from code_assistant_manager.plugins import get_handler
99

1010
logger = logging.getLogger(__name__)
1111

code_assistant_manager/cli/plugins/plugin_install_commands.py

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,13 @@
44
"""
55

66
import logging
7-
from pathlib import Path
87
from typing import Optional
98

109
import typer
1110

1211
from code_assistant_manager.cli.option_utils import resolve_single_app
1312
from code_assistant_manager.menu.base import Colors
14-
from code_assistant_manager.plugins import (
15-
BUILTIN_PLUGIN_REPOS,
16-
PLUGIN_HANDLERS,
17-
VALID_APP_TYPES,
18-
PluginManager,
19-
PluginRepo,
20-
fetch_repo_info_from_url,
21-
get_handler,
22-
parse_github_url,
23-
)
13+
from code_assistant_manager.plugins import VALID_APP_TYPES, get_handler
2414
from code_assistant_manager.plugins.base import BasePluginHandler
2515

2616
logger = logging.getLogger(__name__)

0 commit comments

Comments
 (0)