claude-mpm 5.4.3__py3-none-any.whl → 5.4.14__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.
Potentially problematic release.
This version of claude-mpm might be problematic. Click here for more details.
- claude_mpm/VERSION +1 -1
- claude_mpm/__init__.py +4 -0
- claude_mpm/agents/PM_INSTRUCTIONS.md +39 -0
- claude_mpm/agents/agent_loader.py +3 -27
- claude_mpm/cli/__main__.py +4 -0
- claude_mpm/cli/commands/auto_configure.py +210 -25
- claude_mpm/cli/commands/config.py +88 -2
- claude_mpm/cli/commands/configure.py +85 -43
- claude_mpm/cli/commands/configure_agent_display.py +3 -1
- claude_mpm/cli/commands/mpm_init/core.py +2 -45
- claude_mpm/cli/commands/skills.py +21 -2
- claude_mpm/cli/executor.py +3 -3
- claude_mpm/cli/parsers/config_parser.py +153 -83
- claude_mpm/cli/parsers/skills_parser.py +3 -2
- claude_mpm/cli/startup.py +273 -36
- claude_mpm/commands/mpm-config.md +266 -0
- claude_mpm/core/framework/formatters/content_formatter.py +3 -13
- claude_mpm/core/framework_loader.py +4 -2
- claude_mpm/core/logger.py +13 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +171 -76
- claude_mpm/hooks/claude_hooks/hook_handler.py +2 -0
- claude_mpm/hooks/claude_hooks/installer.py +33 -10
- claude_mpm/hooks/claude_hooks/memory_integration.py +26 -9
- claude_mpm/hooks/claude_hooks/response_tracking.py +2 -3
- claude_mpm/hooks/memory_integration_hook.py +46 -1
- claude_mpm/init.py +0 -19
- claude_mpm/scripts/claude-hook-handler.sh +58 -18
- claude_mpm/services/agents/agent_recommendation_service.py +6 -7
- claude_mpm/services/agents/agent_review_service.py +280 -0
- claude_mpm/services/agents/deployment/agent_discovery_service.py +2 -3
- claude_mpm/services/agents/deployment/agent_template_builder.py +1 -0
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +78 -9
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +13 -0
- claude_mpm/services/agents/git_source_manager.py +14 -0
- claude_mpm/services/agents/loading/base_agent_manager.py +1 -13
- claude_mpm/services/agents/toolchain_detector.py +6 -3
- claude_mpm/services/command_deployment_service.py +71 -8
- claude_mpm/services/git/git_operations_service.py +93 -8
- claude_mpm/services/self_upgrade_service.py +120 -12
- claude_mpm/services/skills/__init__.py +3 -0
- claude_mpm/services/skills/git_skill_source_manager.py +32 -2
- claude_mpm/services/skills/selective_skill_deployer.py +230 -0
- claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
- claude_mpm/services/skills_deployer.py +64 -3
- {claude_mpm-5.4.3.dist-info → claude_mpm-5.4.14.dist-info}/METADATA +47 -8
- {claude_mpm-5.4.3.dist-info → claude_mpm-5.4.14.dist-info}/RECORD +51 -70
- {claude_mpm-5.4.3.dist-info → claude_mpm-5.4.14.dist-info}/entry_points.txt +0 -3
- claude_mpm-5.4.14.dist-info/licenses/LICENSE +94 -0
- claude_mpm-5.4.14.dist-info/licenses/LICENSE-FAQ.md +153 -0
- claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -292
- claude_mpm/agents/BASE_DOCUMENTATION.md +0 -53
- claude_mpm/agents/BASE_ENGINEER.md +0 -658
- claude_mpm/agents/BASE_OPS.md +0 -219
- claude_mpm/agents/BASE_PM.md +0 -480
- claude_mpm/agents/BASE_PROMPT_ENGINEER.md +0 -787
- claude_mpm/agents/BASE_QA.md +0 -167
- claude_mpm/agents/BASE_RESEARCH.md +0 -53
- claude_mpm/agents/base_agent.json +0 -31
- claude_mpm/agents/base_agent_loader.py +0 -601
- claude_mpm/cli/ticket_cli.py +0 -35
- claude_mpm/commands/mpm-config-view.md +0 -150
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -0
- claude_mpm-5.4.3.dist-info/licenses/LICENSE +0 -21
- {claude_mpm-5.4.3.dist-info → claude_mpm-5.4.14.dist-info}/WHEEL +0 -0
- {claude_mpm-5.4.3.dist-info → claude_mpm-5.4.14.dist-info}/top_level.txt +0 -0
|
@@ -400,8 +400,9 @@ class ConfigureCommand(BaseCommand):
|
|
|
400
400
|
# Set deployment status on each agent for display
|
|
401
401
|
deployed_ids = get_deployed_agent_ids()
|
|
402
402
|
for agent in agents:
|
|
403
|
-
#
|
|
404
|
-
|
|
403
|
+
# Use agent_id (technical ID) for comparison, not display name
|
|
404
|
+
agent_id = getattr(agent, "agent_id", agent.name)
|
|
405
|
+
agent_leaf_name = agent_id.split("/")[-1]
|
|
405
406
|
agent.is_deployed = agent_leaf_name in deployed_ids
|
|
406
407
|
|
|
407
408
|
# Filter BASE_AGENT from display (1M-502 Phase 1)
|
|
@@ -1218,7 +1219,9 @@ class ConfigureCommand(BaseCommand):
|
|
|
1218
1219
|
source_label = "Local"
|
|
1219
1220
|
|
|
1220
1221
|
# FIX 2: Check actual deployment status from .claude/agents/ directory
|
|
1221
|
-
|
|
1222
|
+
# Use agent_id (technical ID like "python-engineer") not display name
|
|
1223
|
+
agent_id = getattr(agent, "agent_id", agent.name)
|
|
1224
|
+
is_installed = agent_id in deployed_ids
|
|
1222
1225
|
if is_installed:
|
|
1223
1226
|
status = "[green]Installed[/green]"
|
|
1224
1227
|
else:
|
|
@@ -1248,8 +1251,8 @@ class ConfigureCommand(BaseCommand):
|
|
|
1248
1251
|
recommended_count += 1
|
|
1249
1252
|
break
|
|
1250
1253
|
|
|
1251
|
-
# FIX 1:
|
|
1252
|
-
agent_id_display = agent.name
|
|
1254
|
+
# FIX 1: Show agent_id (technical ID) in first column, not display name
|
|
1255
|
+
agent_id_display = getattr(agent, "agent_id", agent.name)
|
|
1253
1256
|
|
|
1254
1257
|
# Get display name and format it properly
|
|
1255
1258
|
# Raw display_name from YAML may contain underscores (e.g., "agentic_coder_optimizer")
|
|
@@ -1281,7 +1284,10 @@ class ConfigureCommand(BaseCommand):
|
|
|
1281
1284
|
self.console.print("\n[dim]* = recommended for this project[/dim]")
|
|
1282
1285
|
|
|
1283
1286
|
# Show installed vs available count (use deployed_ids for accuracy)
|
|
1284
|
-
|
|
1287
|
+
# Use agent_id (technical ID) for comparison, not display name
|
|
1288
|
+
installed_count = sum(
|
|
1289
|
+
1 for a in agents if getattr(a, "agent_id", a.name) in deployed_ids
|
|
1290
|
+
)
|
|
1285
1291
|
available_count = len(agents) - installed_count
|
|
1286
1292
|
self.console.print(
|
|
1287
1293
|
f"\n[green]✓ {installed_count} installed[/green] | "
|
|
@@ -1326,7 +1332,7 @@ class ConfigureCommand(BaseCommand):
|
|
|
1326
1332
|
all_agents = filter_base_agents(
|
|
1327
1333
|
[
|
|
1328
1334
|
{
|
|
1329
|
-
"agent_id": a.name,
|
|
1335
|
+
"agent_id": getattr(a, "agent_id", a.name),
|
|
1330
1336
|
"name": a.name,
|
|
1331
1337
|
"description": a.description,
|
|
1332
1338
|
"deployed": getattr(a, "is_deployed", False),
|
|
@@ -1352,11 +1358,14 @@ class ConfigureCommand(BaseCommand):
|
|
|
1352
1358
|
recommended_agent_ids = set()
|
|
1353
1359
|
|
|
1354
1360
|
# Build mapping: leaf name -> full path for deployed agents
|
|
1361
|
+
# Use agent_id (technical ID) for comparison, not display name
|
|
1355
1362
|
deployed_full_paths = set()
|
|
1356
1363
|
for agent in agents:
|
|
1357
|
-
|
|
1364
|
+
agent_id = getattr(agent, "agent_id", agent.name)
|
|
1365
|
+
agent_leaf_name = agent_id.split("/")[-1]
|
|
1358
1366
|
if agent_leaf_name in deployed_ids:
|
|
1359
|
-
|
|
1367
|
+
# Store agent_id for selection tracking (not display name)
|
|
1368
|
+
deployed_full_paths.add(agent_id)
|
|
1360
1369
|
|
|
1361
1370
|
# Track current selection state (starts with deployed, updated in loop)
|
|
1362
1371
|
current_selection = deployed_full_paths.copy()
|
|
@@ -1366,7 +1375,9 @@ class ConfigureCommand(BaseCommand):
|
|
|
1366
1375
|
collections = defaultdict(list)
|
|
1367
1376
|
|
|
1368
1377
|
for agent in agents:
|
|
1369
|
-
|
|
1378
|
+
# Use agent_id (technical ID) for comparison, not display name
|
|
1379
|
+
agent_id = getattr(agent, "agent_id", agent.name)
|
|
1380
|
+
if agent_id in {a["agent_id"] for a in all_agents}:
|
|
1370
1381
|
# Determine collection ID
|
|
1371
1382
|
source_type = getattr(agent, "source_type", "local")
|
|
1372
1383
|
if source_type == "remote":
|
|
@@ -1391,7 +1402,7 @@ class ConfigureCommand(BaseCommand):
|
|
|
1391
1402
|
collection_id = "Local Agents"
|
|
1392
1403
|
|
|
1393
1404
|
collections[collection_id].append(agent)
|
|
1394
|
-
agent_map[
|
|
1405
|
+
agent_map[agent_id] = agent
|
|
1395
1406
|
|
|
1396
1407
|
# Monkey-patch questionary symbols for better visibility
|
|
1397
1408
|
questionary.prompts.common.INDICATOR_SELECTED = "[✓]"
|
|
@@ -1406,10 +1417,11 @@ class ConfigureCommand(BaseCommand):
|
|
|
1406
1417
|
agents_in_collection = collections[collection_id]
|
|
1407
1418
|
|
|
1408
1419
|
# Count selected/total agents in collection
|
|
1420
|
+
# Use agent_id for selection tracking, not display name
|
|
1409
1421
|
selected_count = sum(
|
|
1410
1422
|
1
|
|
1411
1423
|
for agent in agents_in_collection
|
|
1412
|
-
if agent.name in current_selection
|
|
1424
|
+
if getattr(agent, "agent_id", agent.name) in current_selection
|
|
1413
1425
|
)
|
|
1414
1426
|
total_count = len(agents_in_collection)
|
|
1415
1427
|
|
|
@@ -1498,20 +1510,25 @@ class ConfigureCommand(BaseCommand):
|
|
|
1498
1510
|
|
|
1499
1511
|
# Add individual agents
|
|
1500
1512
|
for agent in agents_in_category:
|
|
1501
|
-
|
|
1502
|
-
|
|
1513
|
+
# Use agent_id (technical ID) for all tracking/selection
|
|
1514
|
+
agent_id = getattr(agent, "agent_id", agent.name)
|
|
1515
|
+
agent_leaf_name = agent_id.split("/")[-1]
|
|
1516
|
+
raw_display_name = getattr(
|
|
1517
|
+
agent, "display_name", agent_leaf_name
|
|
1518
|
+
)
|
|
1519
|
+
display_name = self._format_display_name(raw_display_name)
|
|
1503
1520
|
|
|
1504
1521
|
# Check if agent is deployed (exists in .claude/agents/)
|
|
1505
1522
|
|
|
1506
1523
|
# Format choice text (no asterisk needed)
|
|
1507
1524
|
choice_text = f" {display_name}"
|
|
1508
1525
|
|
|
1509
|
-
is_selected =
|
|
1526
|
+
is_selected = agent_id in current_selection
|
|
1510
1527
|
|
|
1511
1528
|
choices.append(
|
|
1512
1529
|
Choice(
|
|
1513
1530
|
title=choice_text,
|
|
1514
|
-
value=
|
|
1531
|
+
value=agent_id, # Use agent_id for value
|
|
1515
1532
|
checked=is_selected,
|
|
1516
1533
|
)
|
|
1517
1534
|
)
|
|
@@ -1565,38 +1582,42 @@ class ConfigureCommand(BaseCommand):
|
|
|
1565
1582
|
)
|
|
1566
1583
|
# Add all agents from this collection to current_selection
|
|
1567
1584
|
for agent in collections[collection_id]:
|
|
1568
|
-
|
|
1585
|
+
agent_id = getattr(agent, "agent_id", agent.name)
|
|
1586
|
+
current_selection.add(agent_id)
|
|
1569
1587
|
elif control.startswith("__DESELECT_ALL_"):
|
|
1570
1588
|
collection_id = control.replace("__DESELECT_ALL_", "").replace(
|
|
1571
1589
|
"__", ""
|
|
1572
1590
|
)
|
|
1573
1591
|
# Remove all agents from this collection
|
|
1574
1592
|
for agent in collections[collection_id]:
|
|
1575
|
-
|
|
1593
|
+
agent_id = getattr(agent, "agent_id", agent.name)
|
|
1594
|
+
current_selection.discard(agent_id)
|
|
1576
1595
|
elif control.startswith("__SELECT_REC_"):
|
|
1577
1596
|
collection_id = control.replace("__SELECT_REC_", "").replace(
|
|
1578
1597
|
"__", ""
|
|
1579
1598
|
)
|
|
1580
1599
|
# Add all recommended agents from this collection
|
|
1581
1600
|
for agent in collections[collection_id]:
|
|
1601
|
+
agent_id = getattr(agent, "agent_id", agent.name)
|
|
1582
1602
|
if any(
|
|
1583
|
-
|
|
1584
|
-
or
|
|
1603
|
+
agent_id == rec_id
|
|
1604
|
+
or agent_id.split("/")[-1] == rec_id.split("/")[-1]
|
|
1585
1605
|
for rec_id in recommended_agent_ids
|
|
1586
1606
|
):
|
|
1587
|
-
current_selection.add(
|
|
1607
|
+
current_selection.add(agent_id)
|
|
1588
1608
|
elif control.startswith("__DESELECT_REC_"):
|
|
1589
1609
|
collection_id = control.replace("__DESELECT_REC_", "").replace(
|
|
1590
1610
|
"__", ""
|
|
1591
1611
|
)
|
|
1592
1612
|
# Remove all recommended agents from this collection
|
|
1593
1613
|
for agent in collections[collection_id]:
|
|
1614
|
+
agent_id = getattr(agent, "agent_id", agent.name)
|
|
1594
1615
|
if any(
|
|
1595
|
-
|
|
1596
|
-
or
|
|
1616
|
+
agent_id == rec_id
|
|
1617
|
+
or agent_id.split("/")[-1] == rec_id.split("/")[-1]
|
|
1597
1618
|
for rec_id in recommended_agent_ids
|
|
1598
1619
|
):
|
|
1599
|
-
current_selection.discard(
|
|
1620
|
+
current_selection.discard(agent_id)
|
|
1600
1621
|
|
|
1601
1622
|
# Loop back to re-display with updated selections
|
|
1602
1623
|
continue
|
|
@@ -1734,7 +1755,7 @@ class ConfigureCommand(BaseCommand):
|
|
|
1734
1755
|
all_agents = filter_base_agents(
|
|
1735
1756
|
[
|
|
1736
1757
|
{
|
|
1737
|
-
"agent_id": a.name,
|
|
1758
|
+
"agent_id": getattr(a, "agent_id", a.name),
|
|
1738
1759
|
"name": a.name,
|
|
1739
1760
|
"description": a.description,
|
|
1740
1761
|
"deployed": getattr(a, "is_deployed", False),
|
|
@@ -1753,12 +1774,14 @@ class ConfigureCommand(BaseCommand):
|
|
|
1753
1774
|
return
|
|
1754
1775
|
|
|
1755
1776
|
# Build mapping: leaf name -> full path for deployed agents
|
|
1756
|
-
# This allows comparing deployed_ids (leaf names) with agent.
|
|
1777
|
+
# This allows comparing deployed_ids (leaf names) with agent.agent_id (full paths)
|
|
1757
1778
|
deployed_full_paths = set()
|
|
1758
1779
|
for agent in agents:
|
|
1759
|
-
|
|
1780
|
+
# FIX: Use agent_id (technical ID) instead of display name
|
|
1781
|
+
agent_id = getattr(agent, "agent_id", agent.name)
|
|
1782
|
+
agent_leaf_name = agent_id.split("/")[-1]
|
|
1760
1783
|
if agent_leaf_name in deployed_ids:
|
|
1761
|
-
deployed_full_paths.add(
|
|
1784
|
+
deployed_full_paths.add(agent_id)
|
|
1762
1785
|
|
|
1763
1786
|
# Track current selection state (starts with deployed full paths, updated after each iteration)
|
|
1764
1787
|
current_selection = deployed_full_paths.copy()
|
|
@@ -1770,7 +1793,9 @@ class ConfigureCommand(BaseCommand):
|
|
|
1770
1793
|
collections = defaultdict(list)
|
|
1771
1794
|
|
|
1772
1795
|
for agent in agents:
|
|
1773
|
-
|
|
1796
|
+
# FIX: Use agent_id (technical ID) for comparison
|
|
1797
|
+
agent_id = getattr(agent, "agent_id", agent.name)
|
|
1798
|
+
if agent_id in {a["agent_id"] for a in all_agents}:
|
|
1774
1799
|
# Determine collection ID
|
|
1775
1800
|
source_type = getattr(agent, "source_type", "local")
|
|
1776
1801
|
if source_type == "remote":
|
|
@@ -1789,7 +1814,7 @@ class ConfigureCommand(BaseCommand):
|
|
|
1789
1814
|
collection_id = "local"
|
|
1790
1815
|
|
|
1791
1816
|
collections[collection_id].append(agent)
|
|
1792
|
-
agent_map[
|
|
1817
|
+
agent_map[agent_id] = agent # FIX: Use agent_id as key
|
|
1793
1818
|
|
|
1794
1819
|
# STEP 1: Collection-level selection
|
|
1795
1820
|
self.console.print("\n[bold cyan]Select Agent Collections[/bold cyan]")
|
|
@@ -1809,15 +1834,18 @@ class ConfigureCommand(BaseCommand):
|
|
|
1809
1834
|
|
|
1810
1835
|
# Check if ANY agent in this collection is currently deployed
|
|
1811
1836
|
# This reflects actual deployment state, not just selection
|
|
1837
|
+
# FIX: Use agent_id for comparison with current_selection
|
|
1812
1838
|
any_deployed = any(
|
|
1813
|
-
agent.name in current_selection
|
|
1839
|
+
getattr(agent, "agent_id", agent.name) in current_selection
|
|
1840
|
+
for agent in agents_in_collection
|
|
1814
1841
|
)
|
|
1815
1842
|
|
|
1816
1843
|
# Count deployed agents for display
|
|
1844
|
+
# FIX: Use agent_id for comparison with current_selection
|
|
1817
1845
|
deployed_count = sum(
|
|
1818
1846
|
1
|
|
1819
1847
|
for agent in agents_in_collection
|
|
1820
|
-
if agent.name in current_selection
|
|
1848
|
+
if getattr(agent, "agent_id", agent.name) in current_selection
|
|
1821
1849
|
)
|
|
1822
1850
|
|
|
1823
1851
|
collection_choices.append(
|
|
@@ -1911,17 +1939,23 @@ class ConfigureCommand(BaseCommand):
|
|
|
1911
1939
|
)
|
|
1912
1940
|
|
|
1913
1941
|
# Add individual agents from this collection
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1942
|
+
# FIX: Use agent_id for sorting, comparison, and values
|
|
1943
|
+
for agent in sorted(
|
|
1944
|
+
agents_in_collection,
|
|
1945
|
+
key=lambda a: getattr(a, "agent_id", a.name),
|
|
1946
|
+
):
|
|
1947
|
+
agent_id = getattr(agent, "agent_id", agent.name)
|
|
1948
|
+
raw_display_name = getattr(agent, "display_name", agent.name)
|
|
1949
|
+
display_name = self._format_display_name(raw_display_name)
|
|
1950
|
+
is_selected = agent_id in deployed_full_paths
|
|
1951
|
+
|
|
1952
|
+
choice_text = f"{agent_id}"
|
|
1953
|
+
if display_name and display_name != agent_id:
|
|
1920
1954
|
choice_text += f" - {display_name}"
|
|
1921
1955
|
|
|
1922
1956
|
agent_choices.append(
|
|
1923
1957
|
Choice(
|
|
1924
|
-
title=choice_text, value=
|
|
1958
|
+
title=choice_text, value=agent_id, checked=is_selected
|
|
1925
1959
|
)
|
|
1926
1960
|
)
|
|
1927
1961
|
|
|
@@ -1971,7 +2005,8 @@ class ConfigureCommand(BaseCommand):
|
|
|
1971
2005
|
final_selections = set()
|
|
1972
2006
|
for collection_id in selected_collections:
|
|
1973
2007
|
for agent in collections[collection_id]:
|
|
1974
|
-
|
|
2008
|
+
# FIX: Use agent_id for selection tracking
|
|
2009
|
+
final_selections.add(getattr(agent, "agent_id", agent.name))
|
|
1975
2010
|
|
|
1976
2011
|
# Update current_selection
|
|
1977
2012
|
# This replaces the previous selection entirely with the new collection selections
|
|
@@ -2484,7 +2519,8 @@ class ConfigureCommand(BaseCommand):
|
|
|
2484
2519
|
|
|
2485
2520
|
self.console.print(f"\n[bold]Installed agents ({len(installed)}):[/bold]")
|
|
2486
2521
|
for idx, agent in enumerate(installed, 1):
|
|
2487
|
-
|
|
2522
|
+
raw_display_name = getattr(agent, "display_name", agent.name)
|
|
2523
|
+
display_name = self._format_display_name(raw_display_name)
|
|
2488
2524
|
self.console.print(f" {idx}. {agent.name} - {display_name}")
|
|
2489
2525
|
|
|
2490
2526
|
selection = Prompt.ask("\nEnter agent number to remove (or 'c' to cancel)")
|
|
@@ -2547,7 +2583,8 @@ class ConfigureCommand(BaseCommand):
|
|
|
2547
2583
|
|
|
2548
2584
|
self.console.print(f"\n[bold]Available agents ({len(agents)}):[/bold]")
|
|
2549
2585
|
for idx, agent in enumerate(agents, 1):
|
|
2550
|
-
|
|
2586
|
+
raw_display_name = getattr(agent, "display_name", agent.name)
|
|
2587
|
+
display_name = self._format_display_name(raw_display_name)
|
|
2551
2588
|
self.console.print(f" {idx}. {agent.name} - {display_name}")
|
|
2552
2589
|
|
|
2553
2590
|
selection = Prompt.ask("\nEnter agent number to view (or 'c' to cancel)")
|
|
@@ -2564,7 +2601,12 @@ class ConfigureCommand(BaseCommand):
|
|
|
2564
2601
|
|
|
2565
2602
|
# Basic info
|
|
2566
2603
|
self.console.print(f"[bold]ID:[/bold] {agent.name}")
|
|
2567
|
-
|
|
2604
|
+
raw_display_name = getattr(agent, "display_name", "N/A")
|
|
2605
|
+
display_name = (
|
|
2606
|
+
self._format_display_name(raw_display_name)
|
|
2607
|
+
if raw_display_name != "N/A"
|
|
2608
|
+
else "N/A"
|
|
2609
|
+
)
|
|
2568
2610
|
self.console.print(f"[bold]Name:[/bold] {display_name}")
|
|
2569
2611
|
self.console.print(f"[bold]Description:[/bold] {agent.description}")
|
|
2570
2612
|
|
|
@@ -85,7 +85,9 @@ class AgentDisplay:
|
|
|
85
85
|
|
|
86
86
|
for idx, agent in enumerate(agents, 1):
|
|
87
87
|
# Check if agent is deployed to .claude/agents/
|
|
88
|
-
|
|
88
|
+
# Use agent_id (technical ID) for comparison, not display name
|
|
89
|
+
agent_id = getattr(agent, "agent_id", agent.name)
|
|
90
|
+
agent_leaf_name = agent_id.split("/")[-1]
|
|
89
91
|
is_deployed = agent_leaf_name in deployed_ids
|
|
90
92
|
|
|
91
93
|
# Show "Installed" for deployed agents, "Available" otherwise
|
|
@@ -157,9 +157,8 @@ class MPMInitCommand:
|
|
|
157
157
|
if pre_check_result.get("status") == OperationResult.ERROR:
|
|
158
158
|
return pre_check_result
|
|
159
159
|
|
|
160
|
-
#
|
|
161
|
-
|
|
162
|
-
self._update_gitignore()
|
|
160
|
+
# Note: .gitignore recommendations are now shown in 'mpm config' command
|
|
161
|
+
# instead of automatic updates during initialization
|
|
163
162
|
|
|
164
163
|
# Build the delegation prompt
|
|
165
164
|
if update_mode:
|
|
@@ -401,48 +400,6 @@ class MPMInitCommand:
|
|
|
401
400
|
"warnings": warnings,
|
|
402
401
|
}
|
|
403
402
|
|
|
404
|
-
def _update_gitignore(self) -> None:
|
|
405
|
-
"""Update .gitignore to exclude claude-mpm configuration directories.
|
|
406
|
-
|
|
407
|
-
Ensures that claude-mpm configuration directories are added to .gitignore
|
|
408
|
-
to prevent them from being committed to version control.
|
|
409
|
-
|
|
410
|
-
This is a non-destructive operation that:
|
|
411
|
-
- Creates .gitignore if it doesn't exist
|
|
412
|
-
- Appends missing entries only (never duplicates)
|
|
413
|
-
- Preserves all existing content
|
|
414
|
-
|
|
415
|
-
Standard entries added:
|
|
416
|
-
- .claude-mpm/: Main configuration directory
|
|
417
|
-
- .claude/agents/: Agent runtime files
|
|
418
|
-
"""
|
|
419
|
-
from claude_mpm.utils.gitignore import ensure_claude_mpm_gitignore
|
|
420
|
-
|
|
421
|
-
try:
|
|
422
|
-
result = ensure_claude_mpm_gitignore(str(self.project_path))
|
|
423
|
-
|
|
424
|
-
if result.get("status") == "success":
|
|
425
|
-
if result.get("added"):
|
|
426
|
-
self.console.print(
|
|
427
|
-
f"[green]✓[/green] Updated .gitignore: {', '.join(result['added'])}"
|
|
428
|
-
)
|
|
429
|
-
logger.info(f"Added to .gitignore: {result['added']}")
|
|
430
|
-
elif result.get("existing"):
|
|
431
|
-
logger.debug(f".gitignore already contains: {result['existing']}")
|
|
432
|
-
else:
|
|
433
|
-
# Non-critical error - log but don't fail initialization
|
|
434
|
-
logger.warning(
|
|
435
|
-
f"Could not update .gitignore: {result.get('error', 'Unknown error')}"
|
|
436
|
-
)
|
|
437
|
-
self.console.print(
|
|
438
|
-
f"[yellow]⚠️ Could not update .gitignore: {result.get('error')}[/yellow]"
|
|
439
|
-
)
|
|
440
|
-
|
|
441
|
-
except Exception as e:
|
|
442
|
-
# Non-critical error - log but don't fail initialization
|
|
443
|
-
logger.warning(f"Error updating .gitignore: {e}")
|
|
444
|
-
self.console.print(f"[yellow]⚠️ Could not update .gitignore: {e}[/yellow]")
|
|
445
|
-
|
|
446
403
|
def _build_initialization_prompt(
|
|
447
404
|
self,
|
|
448
405
|
project_type: Optional[str] = None,
|
|
@@ -537,7 +537,7 @@ class SkillsManagementCommand(BaseCommand):
|
|
|
537
537
|
toolchain = getattr(args, "toolchain", None)
|
|
538
538
|
categories = getattr(args, "categories", None)
|
|
539
539
|
force = getattr(args, "force", False)
|
|
540
|
-
all_skills = getattr(args, "
|
|
540
|
+
all_skills = getattr(args, "all_skills", False)
|
|
541
541
|
|
|
542
542
|
if collection:
|
|
543
543
|
console.print(
|
|
@@ -554,17 +554,36 @@ class SkillsManagementCommand(BaseCommand):
|
|
|
554
554
|
"[yellow]No toolchain specified. Use --toolchain to filter by language,[/yellow]"
|
|
555
555
|
)
|
|
556
556
|
console.print(
|
|
557
|
-
"[yellow]or --all to deploy all available skills.[/yellow]\n"
|
|
557
|
+
"[yellow]or --all-skills to deploy all available skills (not just agent-referenced).[/yellow]\n"
|
|
558
558
|
)
|
|
559
559
|
|
|
560
|
+
# Selective deployment is enabled by default (deploy only agent-referenced skills)
|
|
561
|
+
# Use --all-skills to disable selective mode
|
|
560
562
|
result = self.skills_deployer.deploy_skills(
|
|
561
563
|
collection=collection,
|
|
562
564
|
toolchain=toolchain,
|
|
563
565
|
categories=categories,
|
|
564
566
|
force=force,
|
|
567
|
+
selective=not all_skills, # Disable selective mode if --all-skills is set
|
|
565
568
|
)
|
|
566
569
|
|
|
567
570
|
# Display results
|
|
571
|
+
# Show selective mode summary
|
|
572
|
+
if result.get("selective_mode"):
|
|
573
|
+
total_available = result.get("total_available", 0)
|
|
574
|
+
deployed_count = result["deployed_count"]
|
|
575
|
+
console.print(
|
|
576
|
+
f"[cyan]📌 Selective deployment: {deployed_count} agent-referenced skills "
|
|
577
|
+
f"(out of {total_available} available)[/cyan]"
|
|
578
|
+
)
|
|
579
|
+
console.print(
|
|
580
|
+
"[dim]Use --all-skills to deploy all available skills[/dim]\n"
|
|
581
|
+
)
|
|
582
|
+
else:
|
|
583
|
+
console.print(
|
|
584
|
+
"[cyan]📦 Deploying all available skills (selective mode disabled)[/cyan]\n"
|
|
585
|
+
)
|
|
586
|
+
|
|
568
587
|
if result["deployed_count"] > 0:
|
|
569
588
|
console.print(
|
|
570
589
|
f"[green]✓ Deployed {result['deployed_count']} skill(s):[/green]"
|
claude_mpm/cli/executor.py
CHANGED
|
@@ -24,6 +24,7 @@ from .commands import (
|
|
|
24
24
|
show_info,
|
|
25
25
|
)
|
|
26
26
|
from .commands.analyze_code import manage_analyze_code
|
|
27
|
+
from .commands.config import manage_config
|
|
27
28
|
from .commands.dashboard import manage_dashboard
|
|
28
29
|
from .commands.skills import manage_skills
|
|
29
30
|
from .commands.upgrade import upgrade
|
|
@@ -236,9 +237,8 @@ def execute_command(command: str, args) -> int:
|
|
|
236
237
|
CLICommands.MEMORY.value: manage_memory,
|
|
237
238
|
CLICommands.MONITOR.value: manage_monitor,
|
|
238
239
|
CLICommands.DASHBOARD.value: manage_dashboard,
|
|
239
|
-
# Configuration management commands
|
|
240
|
-
#
|
|
241
|
-
CLICommands.CONFIG.value: manage_configure, # Alias to configure
|
|
240
|
+
# Configuration management commands
|
|
241
|
+
CLICommands.CONFIG.value: manage_config, # Unified config with subcommands
|
|
242
242
|
CLICommands.CONFIGURE.value: manage_configure, # Interactive configuration TUI
|
|
243
243
|
CLICommands.AGGREGATE.value: aggregate_command,
|
|
244
244
|
CLICommands.ANALYZE_CODE.value: manage_analyze_code,
|