claude-mpm 4.1.8__py3-none-any.whl → 4.1.11__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.
Files changed (111) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/INSTRUCTIONS.md +26 -1
  3. claude_mpm/agents/agents_metadata.py +57 -0
  4. claude_mpm/agents/templates/.claude-mpm/memories/README.md +17 -0
  5. claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +3 -0
  6. claude_mpm/agents/templates/agent-manager.json +263 -17
  7. claude_mpm/agents/templates/agentic_coder_optimizer.json +222 -0
  8. claude_mpm/agents/templates/code_analyzer.json +18 -8
  9. claude_mpm/agents/templates/engineer.json +1 -1
  10. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +39 -0
  11. claude_mpm/agents/templates/qa.json +1 -1
  12. claude_mpm/agents/templates/research.json +1 -1
  13. claude_mpm/cli/__init__.py +15 -0
  14. claude_mpm/cli/commands/__init__.py +6 -0
  15. claude_mpm/cli/commands/analyze.py +548 -0
  16. claude_mpm/cli/commands/analyze_code.py +524 -0
  17. claude_mpm/cli/commands/configure.py +78 -28
  18. claude_mpm/cli/commands/configure_tui.py +62 -60
  19. claude_mpm/cli/commands/dashboard.py +288 -0
  20. claude_mpm/cli/commands/debug.py +1386 -0
  21. claude_mpm/cli/commands/mpm_init.py +427 -0
  22. claude_mpm/cli/commands/mpm_init_handler.py +83 -0
  23. claude_mpm/cli/parsers/analyze_code_parser.py +170 -0
  24. claude_mpm/cli/parsers/analyze_parser.py +135 -0
  25. claude_mpm/cli/parsers/base_parser.py +44 -0
  26. claude_mpm/cli/parsers/dashboard_parser.py +113 -0
  27. claude_mpm/cli/parsers/debug_parser.py +319 -0
  28. claude_mpm/cli/parsers/mpm_init_parser.py +122 -0
  29. claude_mpm/constants.py +13 -1
  30. claude_mpm/core/framework_loader.py +148 -6
  31. claude_mpm/core/log_manager.py +16 -13
  32. claude_mpm/core/logger.py +1 -1
  33. claude_mpm/core/unified_agent_registry.py +1 -1
  34. claude_mpm/dashboard/.claude-mpm/socketio-instances.json +1 -0
  35. claude_mpm/dashboard/analysis_runner.py +455 -0
  36. claude_mpm/dashboard/static/built/components/activity-tree.js +2 -0
  37. claude_mpm/dashboard/static/built/components/agent-inference.js +1 -1
  38. claude_mpm/dashboard/static/built/components/code-tree.js +2 -0
  39. claude_mpm/dashboard/static/built/components/code-viewer.js +2 -0
  40. claude_mpm/dashboard/static/built/components/event-viewer.js +1 -1
  41. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +1 -1
  42. claude_mpm/dashboard/static/built/components/module-viewer.js +1 -1
  43. claude_mpm/dashboard/static/built/components/session-manager.js +1 -1
  44. claude_mpm/dashboard/static/built/components/working-directory.js +1 -1
  45. claude_mpm/dashboard/static/built/dashboard.js +1 -1
  46. claude_mpm/dashboard/static/built/socket-client.js +1 -1
  47. claude_mpm/dashboard/static/css/activity.css +549 -0
  48. claude_mpm/dashboard/static/css/code-tree.css +1175 -0
  49. claude_mpm/dashboard/static/css/dashboard.css +245 -0
  50. claude_mpm/dashboard/static/dist/components/activity-tree.js +2 -0
  51. claude_mpm/dashboard/static/dist/components/code-tree.js +2 -0
  52. claude_mpm/dashboard/static/dist/components/code-viewer.js +2 -0
  53. claude_mpm/dashboard/static/dist/components/event-viewer.js +1 -1
  54. claude_mpm/dashboard/static/dist/components/session-manager.js +1 -1
  55. claude_mpm/dashboard/static/dist/components/working-directory.js +1 -1
  56. claude_mpm/dashboard/static/dist/dashboard.js +1 -1
  57. claude_mpm/dashboard/static/dist/socket-client.js +1 -1
  58. claude_mpm/dashboard/static/js/components/activity-tree.js +1338 -0
  59. claude_mpm/dashboard/static/js/components/code-tree.js +2535 -0
  60. claude_mpm/dashboard/static/js/components/code-viewer.js +480 -0
  61. claude_mpm/dashboard/static/js/components/event-viewer.js +59 -9
  62. claude_mpm/dashboard/static/js/components/session-manager.js +40 -4
  63. claude_mpm/dashboard/static/js/components/socket-manager.js +12 -0
  64. claude_mpm/dashboard/static/js/components/ui-state-manager.js +4 -0
  65. claude_mpm/dashboard/static/js/components/working-directory.js +17 -1
  66. claude_mpm/dashboard/static/js/dashboard.js +51 -0
  67. claude_mpm/dashboard/static/js/socket-client.js +465 -29
  68. claude_mpm/dashboard/templates/index.html +182 -4
  69. claude_mpm/hooks/claude_hooks/hook_handler.py +182 -5
  70. claude_mpm/hooks/claude_hooks/installer.py +386 -113
  71. claude_mpm/scripts/claude-hook-handler.sh +161 -0
  72. claude_mpm/scripts/socketio_daemon.py +121 -8
  73. claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +2 -2
  74. claude_mpm/services/agents/deployment/agent_record_service.py +1 -2
  75. claude_mpm/services/agents/memory/memory_format_service.py +1 -3
  76. claude_mpm/services/cli/agent_cleanup_service.py +1 -5
  77. claude_mpm/services/cli/agent_dependency_service.py +1 -1
  78. claude_mpm/services/cli/agent_validation_service.py +3 -4
  79. claude_mpm/services/cli/dashboard_launcher.py +2 -3
  80. claude_mpm/services/cli/startup_checker.py +0 -11
  81. claude_mpm/services/core/cache_manager.py +1 -3
  82. claude_mpm/services/core/path_resolver.py +1 -4
  83. claude_mpm/services/core/service_container.py +2 -2
  84. claude_mpm/services/diagnostics/checks/instructions_check.py +1 -2
  85. claude_mpm/services/infrastructure/monitoring/__init__.py +11 -11
  86. claude_mpm/services/infrastructure/monitoring.py +11 -11
  87. claude_mpm/services/project/architecture_analyzer.py +1 -1
  88. claude_mpm/services/project/dependency_analyzer.py +4 -4
  89. claude_mpm/services/project/language_analyzer.py +3 -3
  90. claude_mpm/services/project/metrics_collector.py +3 -6
  91. claude_mpm/services/socketio/event_normalizer.py +64 -0
  92. claude_mpm/services/socketio/handlers/__init__.py +2 -0
  93. claude_mpm/services/socketio/handlers/code_analysis.py +672 -0
  94. claude_mpm/services/socketio/handlers/registry.py +2 -0
  95. claude_mpm/services/socketio/server/connection_manager.py +6 -4
  96. claude_mpm/services/socketio/server/core.py +100 -11
  97. claude_mpm/services/socketio/server/main.py +8 -2
  98. claude_mpm/services/visualization/__init__.py +19 -0
  99. claude_mpm/services/visualization/mermaid_generator.py +938 -0
  100. claude_mpm/tools/__main__.py +208 -0
  101. claude_mpm/tools/code_tree_analyzer.py +1596 -0
  102. claude_mpm/tools/code_tree_builder.py +631 -0
  103. claude_mpm/tools/code_tree_events.py +416 -0
  104. claude_mpm/tools/socketio_debug.py +671 -0
  105. {claude_mpm-4.1.8.dist-info → claude_mpm-4.1.11.dist-info}/METADATA +2 -1
  106. {claude_mpm-4.1.8.dist-info → claude_mpm-4.1.11.dist-info}/RECORD +110 -74
  107. claude_mpm/agents/schema/agent_schema.json +0 -314
  108. {claude_mpm-4.1.8.dist-info → claude_mpm-4.1.11.dist-info}/WHEEL +0 -0
  109. {claude_mpm-4.1.8.dist-info → claude_mpm-4.1.11.dist-info}/entry_points.txt +0 -0
  110. {claude_mpm-4.1.8.dist-info → claude_mpm-4.1.11.dist-info}/licenses/LICENSE +0 -0
  111. {claude_mpm-4.1.8.dist-info → claude_mpm-4.1.11.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,1386 @@
1
+ """
2
+ Debug command for claude-mpm CLI.
3
+
4
+ This module provides comprehensive debugging tools for developers, including:
5
+ - Service debugging (status, dependencies, health)
6
+ - Agent debugging (deployed, memory, trace)
7
+ - Hook system debugging (list, trace, performance)
8
+ - Cache inspection and management
9
+ - Performance profiling and analysis
10
+ - SocketIO event monitoring
11
+ """
12
+
13
+ import contextlib
14
+ import json
15
+ import time
16
+ from collections import defaultdict
17
+ from datetime import datetime
18
+ from pathlib import Path
19
+ from typing import Any, Dict
20
+
21
+ from ...core.logger import get_logger
22
+
23
+
24
+ def manage_debug(args):
25
+ """
26
+ Main entry point for debug commands.
27
+
28
+ Args:
29
+ args: Parsed command-line arguments
30
+
31
+ Returns:
32
+ int: Exit code (0 for success, non-zero for failure)
33
+ """
34
+ # Get logger (it will use the logging level set by main CLI)
35
+ logger = get_logger("debug")
36
+
37
+ # Dispatch to appropriate subcommand
38
+ if args.debug_command == "socketio":
39
+ return debug_socketio(args, logger)
40
+ if args.debug_command == "events":
41
+ # Alias for socketio
42
+ return debug_socketio(args, logger)
43
+ if args.debug_command == "connections":
44
+ return debug_connections(args, logger)
45
+ if args.debug_command == "services":
46
+ return debug_services(args, logger)
47
+ if args.debug_command == "agents":
48
+ return debug_agents(args, logger)
49
+ if args.debug_command == "hooks":
50
+ return debug_hooks(args, logger)
51
+ if args.debug_command == "cache":
52
+ return debug_cache(args, logger)
53
+ if args.debug_command == "performance":
54
+ return debug_performance(args, logger)
55
+ logger.error(f"Unknown debug command: {args.debug_command}")
56
+ return 1
57
+
58
+
59
+ def debug_socketio(args, logger):
60
+ """
61
+ Debug SocketIO events using the professional debugging tool.
62
+
63
+ Args:
64
+ args: Parsed command-line arguments
65
+ logger: Logger instance
66
+
67
+ Returns:
68
+ int: Exit code
69
+ """
70
+ try:
71
+ from ...tools.socketio_debug import DisplayMode, SocketIODebugger
72
+
73
+ logger.info("Starting SocketIO debugger...")
74
+
75
+ # Map display mode from args
76
+ mode = DisplayMode.LIVE # Default
77
+ if args.summary:
78
+ mode = DisplayMode.SUMMARY
79
+ elif args.raw:
80
+ mode = DisplayMode.RAW
81
+ elif args.pretty:
82
+ mode = DisplayMode.PRETTY
83
+ elif args.filter_types:
84
+ mode = DisplayMode.FILTERED
85
+
86
+ # Create debugger instance
87
+ debugger = SocketIODebugger(
88
+ host=args.host,
89
+ port=args.port,
90
+ mode=mode,
91
+ filter_types=args.filter_types,
92
+ output_file=Path(args.output) if args.output else None,
93
+ quiet=args.quiet,
94
+ show_raw=args.raw,
95
+ max_reconnect_attempts=getattr(args, "max_reconnect", 10),
96
+ reconnect_delay=getattr(args, "reconnect_delay", 1.0),
97
+ )
98
+
99
+ # Run the debugger
100
+ success = debugger.run()
101
+
102
+ if success:
103
+ logger.info("SocketIO debugger stopped successfully")
104
+ return 0
105
+ logger.error("SocketIO debugger encountered an error")
106
+ return 1
107
+
108
+ except ImportError as e:
109
+ logger.error(f"Failed to import debugging tool: {e}")
110
+ print(
111
+ "❌ Debugging tool not available. Please ensure all dependencies are installed."
112
+ )
113
+ return 1
114
+ except KeyboardInterrupt:
115
+ logger.info("SocketIO debugger interrupted by user")
116
+ return 0
117
+ except Exception as e:
118
+ logger.error(f"Unexpected error in SocketIO debugger: {e}", exc_info=True)
119
+ return 1
120
+
121
+
122
+ def debug_connections(args, logger):
123
+ """
124
+ Debug active SocketIO connections and server status.
125
+
126
+ Args:
127
+ args: Parsed command-line arguments
128
+ logger: Logger instance
129
+
130
+ Returns:
131
+ int: Exit code
132
+ """
133
+ try:
134
+ import json
135
+
136
+ from ...services.port_manager import PortManager
137
+
138
+ logger.info("Checking SocketIO connections...")
139
+
140
+ # Get port manager
141
+ port_manager = PortManager()
142
+
143
+ # Clean up dead instances
144
+ port_manager.cleanup_dead_instances()
145
+
146
+ # Get active instances
147
+ active_instances = port_manager.list_active_instances()
148
+
149
+ if not active_instances:
150
+ print("No active SocketIO servers found")
151
+ return 0
152
+
153
+ print(f"\n📡 Active SocketIO Servers ({len(active_instances)}):")
154
+ print("-" * 60)
155
+
156
+ for instance in active_instances:
157
+ port = instance.get("port", "unknown")
158
+ pid = instance.get("pid", "unknown")
159
+ start_time = instance.get("start_time", "unknown")
160
+
161
+ print(f"\n🔌 Server on port {port}")
162
+ print(f" PID: {pid}")
163
+ print(f" Started: {start_time}")
164
+
165
+ # Try to check if it's actually responding
166
+ import socket
167
+
168
+ try:
169
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
170
+ s.settimeout(1.0)
171
+ result = s.connect_ex(("127.0.0.1", port))
172
+ if result == 0:
173
+ print(" Status: ✅ Responding")
174
+ else:
175
+ print(" Status: ⚠️ Not responding (may be stale)")
176
+ except Exception as e:
177
+ print(f" Status: ❌ Error checking: {e}")
178
+
179
+ print("\n" + "-" * 60)
180
+ print(f"Total: {len(active_instances)} server(s)")
181
+
182
+ # If verbose, show full JSON
183
+ if getattr(args, "verbose", False):
184
+ print("\nFull instance data:")
185
+ print(json.dumps(active_instances, indent=2, default=str))
186
+
187
+ return 0
188
+
189
+ except Exception as e:
190
+ logger.error(f"Failed to check connections: {e}", exc_info=True)
191
+ return 1
192
+
193
+
194
+ def debug_services(args, logger):
195
+ """
196
+ Debug services: list, status, dependencies, and health.
197
+
198
+ Args:
199
+ args: Parsed command-line arguments
200
+ logger: Logger instance
201
+
202
+ Returns:
203
+ int: Exit code
204
+ """
205
+ try:
206
+ # Import service-related modules
207
+ from ...core.container import DIContainer
208
+
209
+ logger.info("Debugging services...")
210
+
211
+ # Get the global container if available
212
+ container = None
213
+ try:
214
+ # Try to get a container instance if it has the method
215
+ if hasattr(DIContainer, "get_instance"):
216
+ container = DIContainer.get_instance()
217
+ else:
218
+ container = DIContainer()
219
+ except:
220
+ # Create a new container if none exists
221
+ container = DIContainer()
222
+ logger.warning("No active container found, created new instance")
223
+
224
+ if args.list:
225
+ # List all registered services
226
+ print("\n📦 Registered Services:")
227
+ print("=" * 60)
228
+
229
+ services = container._services if hasattr(container, "_services") else {}
230
+ if not services:
231
+ print("No services registered")
232
+ else:
233
+ for service_type, registration in services.items():
234
+ service_name = (
235
+ service_type.__name__
236
+ if hasattr(service_type, "__name__")
237
+ else str(service_type)
238
+ )
239
+ impl_name = (
240
+ registration.implementation.__name__
241
+ if hasattr(registration.implementation, "__name__")
242
+ else str(registration.implementation)
243
+ )
244
+ print(f"\n🔧 {service_name}")
245
+ print(f" Implementation: {impl_name}")
246
+ print(f" Lifetime: {registration.lifetime.value}")
247
+ if registration.instance:
248
+ print(" Status: ✅ Instantiated")
249
+ else:
250
+ print(" Status: ⏸️ Not instantiated")
251
+
252
+ elif args.status:
253
+ # Show service status and health
254
+ print("\n🏥 Service Health Status:")
255
+ print("=" * 60)
256
+
257
+ # Try to get monitoring service
258
+ try:
259
+ from ...services.infrastructure.monitoring import MonitoringService
260
+
261
+ monitor = MonitoringService()
262
+
263
+ # Collect health metrics
264
+ metrics = monitor.collect_metrics()
265
+
266
+ print("\n📊 System Metrics:")
267
+ print(f" CPU Usage: {metrics.get('cpu_percent', 'N/A')}%")
268
+ print(f" Memory Usage: {metrics.get('memory_percent', 'N/A')}%")
269
+ print(f" Disk Usage: {metrics.get('disk_percent', 'N/A')}%")
270
+
271
+ if "network" in metrics:
272
+ net = metrics["network"]
273
+ print("\n🌐 Network:")
274
+ print(f" Bytes Sent: {net.get('bytes_sent', 0):,}")
275
+ print(f" Bytes Received: {net.get('bytes_recv', 0):,}")
276
+
277
+ except Exception as e:
278
+ logger.warning(f"Could not get monitoring metrics: {e}")
279
+ print("⚠️ Monitoring service not available")
280
+
281
+ elif args.dependencies:
282
+ # Show service dependency graph
283
+ print("\n🕸️ Service Dependencies:")
284
+ print("=" * 60)
285
+
286
+ services = container._services if hasattr(container, "_services") else {}
287
+ if not services:
288
+ print("No services registered")
289
+ else:
290
+ # Build dependency graph
291
+ for service_type, registration in services.items():
292
+ service_name = (
293
+ service_type.__name__
294
+ if hasattr(service_type, "__name__")
295
+ else str(service_type)
296
+ )
297
+ print(f"\n📌 {service_name}")
298
+
299
+ if registration.dependencies:
300
+ for dep_name, dep_type in registration.dependencies.items():
301
+ dep_type_name = (
302
+ dep_type.__name__
303
+ if hasattr(dep_type, "__name__")
304
+ else str(dep_type)
305
+ )
306
+ print(f" └─> {dep_name}: {dep_type_name}")
307
+ else:
308
+ print(" └─> No dependencies")
309
+
310
+ elif args.trace:
311
+ # Trace service resolution
312
+ service_name = args.trace
313
+ print(f"\n🔍 Tracing service resolution for: {service_name}")
314
+ print("=" * 60)
315
+
316
+ # Try to find and resolve the service
317
+ services = container._services if hasattr(container, "_services") else {}
318
+ found = False
319
+
320
+ for service_type, registration in services.items():
321
+ type_name = (
322
+ service_type.__name__
323
+ if hasattr(service_type, "__name__")
324
+ else str(service_type)
325
+ )
326
+ if service_name in type_name:
327
+ found = True
328
+ print(f"\n✅ Found service: {type_name}")
329
+ print(f" Implementation: {registration.implementation}")
330
+ print(f" Lifetime: {registration.lifetime.value}")
331
+
332
+ # Try to resolve
333
+ try:
334
+ instance = container.resolve(service_type)
335
+ print(" Resolution: ✅ Success")
336
+ print(f" Instance Type: {type(instance).__name__}")
337
+ except Exception as e:
338
+ print(" Resolution: ❌ Failed")
339
+ print(f" Error: {e}")
340
+ break
341
+
342
+ if not found:
343
+ print(f"❌ Service '{service_name}' not found")
344
+
345
+ else:
346
+ # Default: show summary
347
+ print("\n📊 Services Summary:")
348
+ print("=" * 60)
349
+ services = container._services if hasattr(container, "_services") else {}
350
+ print(f"Total Registered: {len(services)}")
351
+
352
+ # Count by lifetime
353
+ lifetime_counts = defaultdict(int)
354
+ instantiated = 0
355
+
356
+ for registration in services.values():
357
+ lifetime_counts[registration.lifetime.value] += 1
358
+ if registration.instance:
359
+ instantiated += 1
360
+
361
+ print("\nLifetime Distribution:")
362
+ for lifetime, count in lifetime_counts.items():
363
+ print(f" {lifetime}: {count}")
364
+
365
+ print(f"\nInstantiated: {instantiated}/{len(services)}")
366
+
367
+ return 0
368
+
369
+ except Exception as e:
370
+ logger.error(f"Failed to debug services: {e}", exc_info=True)
371
+ return 1
372
+
373
+
374
+ def debug_agents(args, logger):
375
+ """
376
+ Debug agents: deployed agents, memory, and tracing.
377
+
378
+ Args:
379
+ args: Parsed command-line arguments
380
+ logger: Logger instance
381
+
382
+ Returns:
383
+ int: Exit code
384
+ """
385
+ try:
386
+ logger.info("Debugging agents...")
387
+
388
+ if args.deployed:
389
+ # List deployed agents
390
+ from pathlib import Path
391
+
392
+ print("\n🤖 Deployed Agents:")
393
+ print("=" * 60)
394
+
395
+ # Check different deployment locations
396
+ locations = [
397
+ Path.home() / ".claude" / "agents",
398
+ Path.cwd() / ".claude" / "agents",
399
+ ]
400
+
401
+ total_agents = 0
402
+ for location in locations:
403
+ if location.exists():
404
+ print(f"\n📁 Location: {location}")
405
+ agent_files = list(location.glob("*.md"))
406
+ if agent_files:
407
+ for agent_file in agent_files:
408
+ agent_name = agent_file.stem
409
+ size = agent_file.stat().st_size
410
+ modified = datetime.fromtimestamp(
411
+ agent_file.stat().st_mtime
412
+ )
413
+ print(f" • {agent_name}")
414
+ print(f" Size: {size:,} bytes")
415
+ print(
416
+ f" Modified: {modified.strftime('%Y-%m-%d %H:%M:%S')}"
417
+ )
418
+ total_agents += 1
419
+ else:
420
+ print(" No agents found")
421
+
422
+ print(f"\nTotal Agents: {total_agents}")
423
+
424
+ elif args.memory:
425
+ # Show agent memory status
426
+ from ...services.agents.memory import get_memory_manager
427
+
428
+ print("\n🧠 Agent Memory Status:")
429
+ print("=" * 60)
430
+
431
+ try:
432
+ get_memory_manager()
433
+
434
+ # List all memory files
435
+ memory_dir = Path.home() / ".claude" / "memory"
436
+ if not memory_dir.exists():
437
+ memory_dir = Path.cwd() / ".claude" / "memory"
438
+
439
+ if memory_dir.exists():
440
+ memory_files = list(memory_dir.glob("*.json"))
441
+
442
+ total_size = 0
443
+ for mem_file in memory_files:
444
+ agent_name = mem_file.stem
445
+ size = mem_file.stat().st_size
446
+
447
+ # Try to load and analyze memory
448
+ try:
449
+ with open(mem_file) as f:
450
+ memory_data = json.load(f)
451
+
452
+ entry_count = (
453
+ len(memory_data) if isinstance(memory_data, list) else 1
454
+ )
455
+ print(f"\n📝 Agent: {agent_name}")
456
+ print(f" File: {mem_file}")
457
+ print(f" Size: {size:,} bytes")
458
+ print(f" Entries: {entry_count}")
459
+ total_size += size
460
+
461
+ # Show recent entries if requested
462
+ if (
463
+ args.verbose
464
+ and isinstance(memory_data, list)
465
+ and memory_data
466
+ ):
467
+ print(" Recent entries:")
468
+ for entry in memory_data[-3:]:
469
+ timestamp = entry.get("timestamp", "N/A")
470
+ category = entry.get("category", "N/A")
471
+ print(f" - [{timestamp}] {category}")
472
+
473
+ except Exception as e:
474
+ print(f"\n📝 Agent: {agent_name}")
475
+ print(f" ⚠️ Could not parse memory: {e}")
476
+
477
+ print("\n📊 Summary:")
478
+ print(f" Total Memory Files: {len(memory_files)}")
479
+ print(f" Total Size: {total_size:,} bytes")
480
+ else:
481
+ print("No memory directory found")
482
+
483
+ except Exception as e:
484
+ logger.warning(f"Could not access memory manager: {e}")
485
+ print("⚠️ Memory manager not available")
486
+
487
+ elif args.trace:
488
+ # Trace agent execution
489
+ agent_name = args.trace
490
+ print(f"\n🔍 Tracing agent: {agent_name}")
491
+ print("=" * 60)
492
+
493
+ # Look for the agent
494
+ from pathlib import Path
495
+
496
+ # Check different locations
497
+ locations = [
498
+ Path.home() / ".claude" / "agents",
499
+ Path.cwd() / ".claude" / "agents",
500
+ ]
501
+
502
+ found = False
503
+ for location in locations:
504
+ agent_file = location / f"{agent_name}.md"
505
+ if agent_file.exists():
506
+ found = True
507
+ print(f"✅ Agent found: {agent_name}")
508
+ print(f" Location: {agent_file}")
509
+ print(f" Size: {agent_file.stat().st_size:,} bytes")
510
+
511
+ # Read first few lines for type detection
512
+ with open(agent_file) as f:
513
+ lines = f.readlines()[:10]
514
+ for line in lines:
515
+ if "role:" in line.lower():
516
+ print(f" Role: {line.split(':')[1].strip()}")
517
+ elif "type:" in line.lower():
518
+ print(f" Type: {line.split(':')[1].strip()}")
519
+ break
520
+
521
+ if not found:
522
+ print(f"❌ Agent '{agent_name}' not found")
523
+
524
+ else:
525
+ # Default: show summary
526
+ print("\n📊 Agents Summary:")
527
+ print("=" * 60)
528
+
529
+ # Count agents in different locations
530
+ locations = [
531
+ (Path.home() / ".claude" / "agents", "User"),
532
+ (Path.cwd() / ".claude" / "agents", "Project"),
533
+ ]
534
+
535
+ total = 0
536
+ for location, label in locations:
537
+ if location.exists():
538
+ count = len(list(location.glob("*.md")))
539
+ print(f"{label} Agents: {count}")
540
+ total += count
541
+
542
+ print(f"\nTotal Agents: {total}")
543
+
544
+ return 0
545
+
546
+ except Exception as e:
547
+ logger.error(f"Failed to debug agents: {e}", exc_info=True)
548
+ return 1
549
+
550
+
551
+ def debug_hooks(args, logger):
552
+ """
553
+ Debug hook system: list hooks, trace execution, analyze performance.
554
+
555
+ Args:
556
+ args: Parsed command-line arguments
557
+ logger: Logger instance
558
+
559
+ Returns:
560
+ int: Exit code
561
+ """
562
+ try:
563
+ from ...services.hook_service import HookService
564
+
565
+ logger.info("Debugging hooks...")
566
+
567
+ # Try to get the hook service
568
+ hook_service = HookService()
569
+
570
+ if args.list:
571
+ # List all registered hooks
572
+ print("\n🪝 Registered Hooks:")
573
+ print("=" * 60)
574
+
575
+ print("\n📥 Pre-Delegation Hooks:")
576
+ if hook_service.pre_delegation_hooks:
577
+ for hook in hook_service.pre_delegation_hooks:
578
+ print(f" • {hook.name}")
579
+ print(f" Priority: {hook.priority}")
580
+ print(f" Enabled: {hook.enabled}")
581
+ if hasattr(hook, "description"):
582
+ print(f" Description: {hook.description}")
583
+ else:
584
+ print(" No pre-delegation hooks registered")
585
+
586
+ print("\n📤 Post-Delegation Hooks:")
587
+ if hook_service.post_delegation_hooks:
588
+ for hook in hook_service.post_delegation_hooks:
589
+ print(f" • {hook.name}")
590
+ print(f" Priority: {hook.priority}")
591
+ print(f" Enabled: {hook.enabled}")
592
+ if hasattr(hook, "description"):
593
+ print(f" Description: {hook.description}")
594
+ else:
595
+ print(" No post-delegation hooks registered")
596
+
597
+ # Show statistics
598
+ print("\n📊 Hook Statistics:")
599
+ print(
600
+ f" Pre-delegation executed: {hook_service.stats.get('pre_delegation_executed', 0)}"
601
+ )
602
+ print(
603
+ f" Post-delegation executed: {hook_service.stats.get('post_delegation_executed', 0)}"
604
+ )
605
+ print(f" Errors: {hook_service.stats.get('errors', 0)}")
606
+
607
+ elif args.trace:
608
+ # Trace hook execution
609
+ hook_name = args.trace
610
+ print(f"\n🔍 Tracing hook: {hook_name}")
611
+ print("=" * 60)
612
+
613
+ found = False
614
+
615
+ # Search in pre-delegation hooks
616
+ for hook in hook_service.pre_delegation_hooks:
617
+ if hook_name.lower() in hook.name.lower():
618
+ found = True
619
+ print(f"\n✅ Found pre-delegation hook: {hook.name}")
620
+ print(f" Priority: {hook.priority}")
621
+ print(f" Enabled: {hook.enabled}")
622
+ print(f" Type: {type(hook).__name__}")
623
+
624
+ # Test execution
625
+ if args.test:
626
+ print("\n🧪 Test Execution:")
627
+ from ...hooks.base_hook import HookContext
628
+
629
+ test_context = HookContext(
630
+ agent_name="test_agent",
631
+ task="test_task",
632
+ metadata={"test": True},
633
+ )
634
+
635
+ try:
636
+ start_time = time.time()
637
+ result = hook.execute(test_context)
638
+ elapsed = time.time() - start_time
639
+
640
+ print(" Status: ✅ Success")
641
+ print(f" Execution Time: {elapsed:.3f}s")
642
+ print(f" Modified: {result.context_modified}")
643
+ if result.error:
644
+ print(f" Error: {result.error}")
645
+ except Exception as e:
646
+ print(" Status: ❌ Failed")
647
+ print(f" Error: {e}")
648
+ break
649
+
650
+ # Search in post-delegation hooks
651
+ for hook in hook_service.post_delegation_hooks:
652
+ if hook_name.lower() in hook.name.lower():
653
+ found = True
654
+ print(f"\n✅ Found post-delegation hook: {hook.name}")
655
+ print(f" Priority: {hook.priority}")
656
+ print(f" Enabled: {hook.enabled}")
657
+ print(f" Type: {type(hook).__name__}")
658
+ break
659
+
660
+ if not found:
661
+ print(f"❌ Hook '{hook_name}' not found")
662
+
663
+ elif args.performance:
664
+ # Analyze hook performance
665
+ print("\n⚡ Hook Performance Analysis:")
666
+ print("=" * 60)
667
+
668
+ # Performance test each hook
669
+ print("\n📥 Pre-Delegation Hooks Performance:")
670
+ for hook in hook_service.pre_delegation_hooks:
671
+ from ...hooks.base_hook import HookContext
672
+
673
+ test_context = HookContext(
674
+ agent_name="perf_test", task="performance test", metadata={}
675
+ )
676
+
677
+ # Run multiple iterations
678
+ iterations = 10
679
+ times = []
680
+
681
+ for _ in range(iterations):
682
+ try:
683
+ start = time.time()
684
+ hook.execute(test_context)
685
+ elapsed = time.time() - start
686
+ times.append(elapsed)
687
+ except:
688
+ pass
689
+
690
+ if times:
691
+ avg_time = sum(times) / len(times)
692
+ min_time = min(times)
693
+ max_time = max(times)
694
+
695
+ print(f"\n {hook.name}:")
696
+ print(f" Average: {avg_time*1000:.2f}ms")
697
+ print(f" Min: {min_time*1000:.2f}ms")
698
+ print(f" Max: {max_time*1000:.2f}ms")
699
+
700
+ else:
701
+ # Default: show summary
702
+ print("\n📊 Hooks Summary:")
703
+ print("=" * 60)
704
+ print(f"Pre-delegation hooks: {len(hook_service.pre_delegation_hooks)}")
705
+ print(f"Post-delegation hooks: {len(hook_service.post_delegation_hooks)}")
706
+ print("\nExecution Statistics:")
707
+ print(
708
+ f" Pre-delegation executed: {hook_service.stats.get('pre_delegation_executed', 0)}"
709
+ )
710
+ print(
711
+ f" Post-delegation executed: {hook_service.stats.get('post_delegation_executed', 0)}"
712
+ )
713
+ print(f" Total errors: {hook_service.stats.get('errors', 0)}")
714
+
715
+ return 0
716
+
717
+ except Exception as e:
718
+ logger.error(f"Failed to debug hooks: {e}", exc_info=True)
719
+ return 1
720
+
721
+
722
+ def debug_cache(args, logger):
723
+ """
724
+ Debug cache: inspect, clear, and analyze cache performance.
725
+
726
+ Args:
727
+ args: Parsed command-line arguments
728
+ logger: Logger instance
729
+
730
+ Returns:
731
+ int: Exit code
732
+ """
733
+ try:
734
+ from ...services.core.cache_manager import CacheManager
735
+
736
+ logger.info("Debugging cache...")
737
+
738
+ if args.inspect:
739
+ # Inspect cache contents
740
+ print("\n🗄️ Cache Inspection:")
741
+ print("=" * 60)
742
+
743
+ # Get cache directory
744
+ cache_dir = Path.home() / ".cache" / "claude-mpm"
745
+ if not cache_dir.exists():
746
+ print("No cache directory found")
747
+ return 0
748
+
749
+ # Analyze cache files
750
+ cache_files = list(cache_dir.rglob("*"))
751
+ total_size = 0
752
+ file_count = 0
753
+
754
+ categories = defaultdict(list)
755
+
756
+ for file_path in cache_files:
757
+ if file_path.is_file():
758
+ file_count += 1
759
+ size = file_path.stat().st_size
760
+ total_size += size
761
+
762
+ # Categorize by parent directory
763
+ category = file_path.parent.name
764
+ categories[category].append((file_path.name, size))
765
+
766
+ print("\n📊 Cache Statistics:")
767
+ print(f" Location: {cache_dir}")
768
+ print(f" Total Files: {file_count}")
769
+ print(
770
+ f" Total Size: {total_size:,} bytes ({total_size/1024/1024:.2f} MB)"
771
+ )
772
+
773
+ print("\n📁 Categories:")
774
+ for category, files in categories.items():
775
+ cat_size = sum(size for _, size in files)
776
+ print(f"\n {category}:")
777
+ print(f" Files: {len(files)}")
778
+ print(f" Size: {cat_size:,} bytes")
779
+
780
+ if args.verbose:
781
+ # Show individual files
782
+ for name, size in sorted(files, key=lambda x: x[1], reverse=True)[
783
+ :5
784
+ ]:
785
+ print(f" • {name}: {size:,} bytes")
786
+
787
+ elif args.clear:
788
+ # Clear cache
789
+ print("\n🧹 Clearing cache...")
790
+ print("=" * 60)
791
+
792
+ cache_dir = Path.home() / ".cache" / "claude-mpm"
793
+
794
+ if not cache_dir.exists():
795
+ print("No cache to clear")
796
+ return 0
797
+
798
+ # Count files before clearing
799
+ files_before = list(cache_dir.rglob("*"))
800
+ file_count = len([f for f in files_before if f.is_file()])
801
+
802
+ if (
803
+ args.confirm
804
+ or input(f"Clear {file_count} cache files? (y/N): ").lower() == "y"
805
+ ):
806
+ # Clear cache
807
+ import shutil
808
+
809
+ try:
810
+ shutil.rmtree(cache_dir)
811
+ print(f"✅ Cleared {file_count} cache files")
812
+ except Exception as e:
813
+ print(f"❌ Failed to clear cache: {e}")
814
+ return 1
815
+ else:
816
+ print("Cache clear cancelled")
817
+
818
+ elif args.stats:
819
+ # Show cache performance statistics
820
+ print("\n📈 Cache Performance Statistics:")
821
+ print("=" * 60)
822
+
823
+ # Try to get cache manager
824
+ cache_manager = CacheManager()
825
+
826
+ # Simulate cache operations to gather stats
827
+ print("\n🔄 Cache TTL Configuration:")
828
+ print(f" Capabilities TTL: {cache_manager.capabilities_ttl}s")
829
+ print(f" Deployed Agents TTL: {cache_manager.deployed_agents_ttl}s")
830
+ print(f" Metadata TTL: {cache_manager.metadata_ttl}s")
831
+ print(f" Memories TTL: {cache_manager.memories_ttl}s")
832
+
833
+ # Check cache status
834
+ current_time = time.time()
835
+
836
+ print("\n⏱️ Cache Status:")
837
+
838
+ # Check capabilities cache
839
+ if cache_manager._capabilities_cache:
840
+ age = current_time - cache_manager._capabilities_cache_time
841
+ status = (
842
+ "✅ Valid" if age < cache_manager.capabilities_ttl else "❌ Expired"
843
+ )
844
+ print(f" Capabilities: {status} (age: {age:.1f}s)")
845
+ else:
846
+ print(" Capabilities: ⚫ Empty")
847
+
848
+ # Check deployed agents cache
849
+ if cache_manager._deployed_agents_cache:
850
+ age = current_time - cache_manager._deployed_agents_cache_time
851
+ status = (
852
+ "✅ Valid"
853
+ if age < cache_manager.deployed_agents_ttl
854
+ else "❌ Expired"
855
+ )
856
+ print(f" Deployed Agents: {status} (age: {age:.1f}s)")
857
+ else:
858
+ print(" Deployed Agents: ⚫ Empty")
859
+
860
+ else:
861
+ # Default: show summary
862
+ print("\n📊 Cache Summary:")
863
+ print("=" * 60)
864
+
865
+ cache_dir = Path.home() / ".cache" / "claude-mpm"
866
+
867
+ if cache_dir.exists():
868
+ cache_files = list(cache_dir.rglob("*"))
869
+ file_count = len([f for f in cache_files if f.is_file()])
870
+ total_size = sum(f.stat().st_size for f in cache_files if f.is_file())
871
+
872
+ print(f"Location: {cache_dir}")
873
+ print(f"Files: {file_count}")
874
+ print(f"Size: {total_size:,} bytes ({total_size/1024/1024:.2f} MB)")
875
+ else:
876
+ print("No cache found")
877
+
878
+ return 0
879
+
880
+ except Exception as e:
881
+ logger.error(f"Failed to debug cache: {e}", exc_info=True)
882
+ return 1
883
+
884
+
885
+ def debug_performance(args, logger):
886
+ """
887
+ Debug performance: profile operations, analyze bottlenecks.
888
+
889
+ Args:
890
+ args: Parsed command-line arguments
891
+ logger: Logger instance
892
+
893
+ Returns:
894
+ int: Exit code
895
+ """
896
+ try:
897
+ logger.info("Running performance analysis...")
898
+
899
+ print("\n⚡ Performance Analysis:")
900
+ print("=" * 60)
901
+
902
+ if args.profile:
903
+ # Profile specific operation
904
+ operation = args.profile
905
+ print(f"\n🔍 Profiling operation: {operation}")
906
+
907
+ import cProfile
908
+ import pstats
909
+ from io import StringIO
910
+
911
+ profiler = cProfile.Profile()
912
+
913
+ # Map operation to actual function
914
+ operations = {
915
+ "agent_load": lambda: _profile_agent_load(),
916
+ "service_init": lambda: _profile_service_init(),
917
+ "cache_ops": lambda: _profile_cache_operations(),
918
+ "memory_ops": lambda: _profile_memory_operations(),
919
+ }
920
+
921
+ if operation in operations:
922
+ print("Starting profile...")
923
+
924
+ profiler.enable()
925
+ start_time = time.time()
926
+
927
+ try:
928
+ operations[operation]()
929
+ except Exception as e:
930
+ print(f"⚠️ Operation failed: {e}")
931
+
932
+ elapsed = time.time() - start_time
933
+ profiler.disable()
934
+
935
+ # Print statistics
936
+ print(f"\n✅ Profile complete (elapsed: {elapsed:.3f}s)")
937
+
938
+ s = StringIO()
939
+ ps = pstats.Stats(profiler, stream=s).sort_stats("cumulative")
940
+ ps.print_stats(20) # Top 20 functions
941
+
942
+ print("\n📊 Top Functions by Cumulative Time:")
943
+ print(s.getvalue())
944
+ else:
945
+ print(f"❌ Unknown operation: {operation}")
946
+ print(" Available: agent_load, service_init, cache_ops, memory_ops")
947
+
948
+ elif args.benchmark:
949
+ # Run benchmarks
950
+ print("\n🏃 Running benchmarks...")
951
+
952
+ benchmarks = [
953
+ ("Service Container Resolution", _benchmark_service_resolution),
954
+ ("Cache Operations", _benchmark_cache_operations),
955
+ ("Agent Loading", _benchmark_agent_loading),
956
+ ("Hook Execution", _benchmark_hook_execution),
957
+ ]
958
+
959
+ results = []
960
+
961
+ for name, benchmark_func in benchmarks:
962
+ print(f"\n▶️ {name}...")
963
+ try:
964
+ result = benchmark_func()
965
+ results.append((name, result))
966
+ print(f" Time: {result['time']:.3f}s")
967
+ print(f" Ops/sec: {result.get('ops_per_sec', 'N/A')}")
968
+ except Exception as e:
969
+ print(f" ❌ Failed: {e}")
970
+ results.append((name, {"error": str(e)}))
971
+
972
+ # Summary
973
+ print("\n📊 Benchmark Summary:")
974
+ print("=" * 60)
975
+ for name, result in results:
976
+ if "error" in result:
977
+ print(f"{name}: ❌ Failed")
978
+ else:
979
+ print(f"{name}: {result['time']:.3f}s")
980
+
981
+ else:
982
+ # Default: show system performance
983
+ print("\n📊 System Performance:")
984
+
985
+ try:
986
+ import psutil
987
+ except ImportError:
988
+ print("⚠️ psutil not installed. Install with: pip install psutil")
989
+ return 0
990
+
991
+ # CPU info
992
+ print("\n🖥️ CPU:")
993
+ print(f" Usage: {psutil.cpu_percent(interval=1)}%")
994
+ print(
995
+ f" Cores: {psutil.cpu_count(logical=False)} physical, {psutil.cpu_count()} logical"
996
+ )
997
+
998
+ # Memory info
999
+ mem = psutil.virtual_memory()
1000
+ print("\n💾 Memory:")
1001
+ print(f" Total: {mem.total/1024/1024/1024:.2f} GB")
1002
+ print(f" Used: {mem.used/1024/1024/1024:.2f} GB ({mem.percent}%)")
1003
+ print(f" Available: {mem.available/1024/1024/1024:.2f} GB")
1004
+
1005
+ # Disk info
1006
+ disk = psutil.disk_usage("/")
1007
+ print("\n💿 Disk:")
1008
+ print(f" Total: {disk.total/1024/1024/1024:.2f} GB")
1009
+ print(f" Used: {disk.used/1024/1024/1024:.2f} GB ({disk.percent}%)")
1010
+ print(f" Free: {disk.free/1024/1024/1024:.2f} GB")
1011
+
1012
+ # Process info
1013
+ process = psutil.Process()
1014
+ print("\n📦 Current Process:")
1015
+ print(f" PID: {process.pid}")
1016
+ print(f" Memory: {process.memory_info().rss/1024/1024:.2f} MB")
1017
+ print(f" CPU: {process.cpu_percent()}%")
1018
+ print(f" Threads: {process.num_threads()}")
1019
+
1020
+ return 0
1021
+
1022
+ except Exception as e:
1023
+ logger.error(f"Failed to run performance analysis: {e}", exc_info=True)
1024
+ return 1
1025
+
1026
+
1027
+ # Helper functions for profiling
1028
+ def _profile_agent_load():
1029
+ """Profile agent loading operation."""
1030
+ from ...services.agents.deployment import AgentDeploymentService
1031
+
1032
+ service = AgentDeploymentService()
1033
+ # Simulate loading agents
1034
+ for _ in range(10):
1035
+ with contextlib.suppress(Exception):
1036
+ service.list_agents()
1037
+
1038
+
1039
+ def _profile_service_init():
1040
+ """Profile service initialization."""
1041
+ from ...core.container import DIContainer
1042
+
1043
+ container = DIContainer()
1044
+ # Register and resolve services
1045
+
1046
+ class TestService:
1047
+ pass
1048
+
1049
+ for i in range(20):
1050
+ container.register(f"TestService{i}", TestService)
1051
+ container.resolve(f"TestService{i}")
1052
+
1053
+
1054
+ def _profile_cache_operations():
1055
+ """Profile cache operations."""
1056
+ from ...services.core.cache_manager import CacheManager
1057
+
1058
+ cache = CacheManager()
1059
+
1060
+ # Simulate cache operations
1061
+ for i in range(100):
1062
+ cache.set_capabilities(f"test_cap_{i}")
1063
+ cache.get_capabilities()
1064
+ cache.invalidate_capabilities()
1065
+
1066
+
1067
+ def _profile_memory_operations():
1068
+ """Profile memory operations."""
1069
+ from ...services.agents.memory import AgentMemoryManager
1070
+
1071
+ memory = AgentMemoryManager("test_agent")
1072
+
1073
+ # Simulate memory operations
1074
+ for i in range(50):
1075
+ try:
1076
+ memory.add_memory(f"category_{i}", {"data": f"test_{i}"})
1077
+ memory.get_memories()
1078
+ except:
1079
+ pass
1080
+
1081
+
1082
+ # Helper functions for benchmarking
1083
+ def _benchmark_service_resolution() -> Dict[str, Any]:
1084
+ """Benchmark service container resolution."""
1085
+ from ...core.container import DIContainer
1086
+
1087
+ container = DIContainer()
1088
+
1089
+ class TestService:
1090
+ pass
1091
+
1092
+ container.register(TestService, TestService)
1093
+
1094
+ iterations = 1000
1095
+ start = time.time()
1096
+
1097
+ for _ in range(iterations):
1098
+ container.resolve(TestService)
1099
+
1100
+ elapsed = time.time() - start
1101
+
1102
+ return {
1103
+ "time": elapsed,
1104
+ "iterations": iterations,
1105
+ "ops_per_sec": iterations / elapsed,
1106
+ }
1107
+
1108
+
1109
+ def _benchmark_cache_operations() -> Dict[str, Any]:
1110
+ """Benchmark cache operations."""
1111
+ from ...services.core.cache_manager import CacheManager
1112
+
1113
+ cache = CacheManager()
1114
+ iterations = 1000
1115
+
1116
+ start = time.time()
1117
+
1118
+ for i in range(iterations):
1119
+ cache.set_capabilities(f"test_{i}")
1120
+ cache.get_capabilities()
1121
+
1122
+ elapsed = time.time() - start
1123
+
1124
+ return {
1125
+ "time": elapsed,
1126
+ "iterations": iterations * 2, # set + get
1127
+ "ops_per_sec": (iterations * 2) / elapsed,
1128
+ }
1129
+
1130
+
1131
+ def _benchmark_agent_loading() -> Dict[str, Any]:
1132
+ """Benchmark agent loading."""
1133
+ from pathlib import Path
1134
+
1135
+ iterations = 100
1136
+ start = time.time()
1137
+
1138
+ for _ in range(iterations):
1139
+ # Simulate agent discovery
1140
+ agent_dir = Path.home() / ".claude" / "agents"
1141
+ if agent_dir.exists():
1142
+ list(agent_dir.glob("*.md"))
1143
+
1144
+ elapsed = time.time() - start
1145
+
1146
+ return {
1147
+ "time": elapsed,
1148
+ "iterations": iterations,
1149
+ "ops_per_sec": iterations / elapsed,
1150
+ }
1151
+
1152
+
1153
+ def _benchmark_hook_execution() -> Dict[str, Any]:
1154
+ """Benchmark hook execution."""
1155
+ from ...hooks.base_hook import HookContext, HookResult, PreDelegationHook
1156
+
1157
+ class TestHook(PreDelegationHook):
1158
+ def execute(self, context: HookContext) -> HookResult:
1159
+ return HookResult(context=context)
1160
+
1161
+ hook = TestHook(name="test", priority=0)
1162
+ context = HookContext(agent_name="test", task="test", metadata={})
1163
+
1164
+ iterations = 1000
1165
+ start = time.time()
1166
+
1167
+ for _ in range(iterations):
1168
+ hook.execute(context)
1169
+
1170
+ elapsed = time.time() - start
1171
+
1172
+ return {
1173
+ "time": elapsed,
1174
+ "iterations": iterations,
1175
+ "ops_per_sec": iterations / elapsed,
1176
+ }
1177
+
1178
+
1179
+ def add_debug_parser(subparsers):
1180
+ """
1181
+ Add the debug subparser with debugging commands.
1182
+
1183
+ This function is called by the main parser to add debug commands.
1184
+
1185
+ Args:
1186
+ subparsers: The subparsers object from the main parser
1187
+
1188
+ Returns:
1189
+ The configured debug subparser
1190
+ """
1191
+
1192
+ # Main debug parser
1193
+ debug_parser = subparsers.add_parser(
1194
+ "debug",
1195
+ help="Development debugging tools",
1196
+ description="Tools for debugging and monitoring claude-mpm components",
1197
+ )
1198
+
1199
+ # Add debug subcommands
1200
+ debug_subparsers = debug_parser.add_subparsers(
1201
+ dest="debug_command", help="Debug commands", metavar="SUBCOMMAND"
1202
+ )
1203
+
1204
+ # SocketIO debugging
1205
+ socketio_parser = debug_subparsers.add_parser(
1206
+ "socketio",
1207
+ help="Debug SocketIO events in real-time",
1208
+ aliases=["events"],
1209
+ description="Professional SocketIO event monitoring and analysis tool",
1210
+ )
1211
+
1212
+ # Connection options
1213
+ socketio_parser.add_argument(
1214
+ "--host", default="localhost", help="SocketIO server host (default: localhost)"
1215
+ )
1216
+ socketio_parser.add_argument(
1217
+ "--port", type=int, default=8765, help="SocketIO server port (default: 8765)"
1218
+ )
1219
+
1220
+ # Display options
1221
+ display_group = socketio_parser.add_mutually_exclusive_group()
1222
+ display_group.add_argument(
1223
+ "--live",
1224
+ action="store_true",
1225
+ default=True,
1226
+ help="Live event monitoring (default)",
1227
+ )
1228
+ display_group.add_argument(
1229
+ "--summary", action="store_true", help="Show aggregated statistics and summary"
1230
+ )
1231
+ display_group.add_argument(
1232
+ "--raw", action="store_true", help="Display raw JSON output"
1233
+ )
1234
+ display_group.add_argument(
1235
+ "--pretty", action="store_true", help="Enhanced formatted output with colors"
1236
+ )
1237
+
1238
+ # Filtering
1239
+ socketio_parser.add_argument(
1240
+ "--filter",
1241
+ nargs="+",
1242
+ dest="filter_types",
1243
+ help="Filter specific event types (e.g., PreToolUse PostToolUse)",
1244
+ )
1245
+
1246
+ # Output options
1247
+ socketio_parser.add_argument(
1248
+ "--output", "-o", help="Save events to file (JSONL format)"
1249
+ )
1250
+ socketio_parser.add_argument(
1251
+ "--quiet",
1252
+ "-q",
1253
+ action="store_true",
1254
+ help="Suppress output except errors (useful with --output)",
1255
+ )
1256
+
1257
+ # Connection resilience
1258
+ socketio_parser.add_argument(
1259
+ "--max-reconnect",
1260
+ type=int,
1261
+ default=10,
1262
+ help="Maximum reconnection attempts (default: 10)",
1263
+ )
1264
+ socketio_parser.add_argument(
1265
+ "--reconnect-delay",
1266
+ type=float,
1267
+ default=1.0,
1268
+ help="Reconnection delay in seconds (default: 1.0)",
1269
+ )
1270
+
1271
+ # Connection debugging
1272
+ connections_parser = debug_subparsers.add_parser(
1273
+ "connections",
1274
+ help="Show active SocketIO server connections",
1275
+ description="Display information about active SocketIO servers and their status",
1276
+ )
1277
+ connections_parser.add_argument(
1278
+ "--verbose",
1279
+ "-v",
1280
+ action="store_true",
1281
+ help="Show detailed connection information",
1282
+ )
1283
+
1284
+ # Services debugging
1285
+ services_parser = debug_subparsers.add_parser(
1286
+ "services",
1287
+ help="Debug service container and dependencies",
1288
+ description="Inspect services, dependencies, and health status",
1289
+ )
1290
+ services_group = services_parser.add_mutually_exclusive_group()
1291
+ services_group.add_argument(
1292
+ "--list", action="store_true", help="List all registered services"
1293
+ )
1294
+ services_group.add_argument(
1295
+ "--status", action="store_true", help="Show service health status"
1296
+ )
1297
+ services_group.add_argument(
1298
+ "--dependencies", action="store_true", help="Show service dependency graph"
1299
+ )
1300
+ services_group.add_argument(
1301
+ "--trace",
1302
+ metavar="SERVICE",
1303
+ help="Trace service resolution for specific service",
1304
+ )
1305
+
1306
+ # Agents debugging
1307
+ agents_parser = debug_subparsers.add_parser(
1308
+ "agents",
1309
+ help="Debug deployed agents and memory",
1310
+ description="Inspect deployed agents, memory, and traces",
1311
+ )
1312
+ agents_group = agents_parser.add_mutually_exclusive_group()
1313
+ agents_group.add_argument(
1314
+ "--deployed", action="store_true", help="List all deployed agents"
1315
+ )
1316
+ agents_group.add_argument(
1317
+ "--memory", action="store_true", help="Show agent memory status"
1318
+ )
1319
+ agents_group.add_argument(
1320
+ "--trace", metavar="AGENT", help="Trace specific agent execution"
1321
+ )
1322
+ agents_parser.add_argument(
1323
+ "--verbose", "-v", action="store_true", help="Show detailed information"
1324
+ )
1325
+
1326
+ # Hooks debugging
1327
+ hooks_parser = debug_subparsers.add_parser(
1328
+ "hooks",
1329
+ help="Debug hook system",
1330
+ description="List hooks, trace execution, analyze performance",
1331
+ )
1332
+ hooks_group = hooks_parser.add_mutually_exclusive_group()
1333
+ hooks_group.add_argument(
1334
+ "--list", action="store_true", help="List all registered hooks"
1335
+ )
1336
+ hooks_group.add_argument(
1337
+ "--trace", metavar="HOOK", help="Trace specific hook execution"
1338
+ )
1339
+ hooks_group.add_argument(
1340
+ "--performance", action="store_true", help="Analyze hook performance"
1341
+ )
1342
+ hooks_parser.add_argument(
1343
+ "--test", action="store_true", help="Run test execution when tracing"
1344
+ )
1345
+
1346
+ # Cache debugging
1347
+ cache_parser = debug_subparsers.add_parser(
1348
+ "cache",
1349
+ help="Debug cache system",
1350
+ description="Inspect, clear, and analyze cache",
1351
+ )
1352
+ cache_group = cache_parser.add_mutually_exclusive_group()
1353
+ cache_group.add_argument(
1354
+ "--inspect", action="store_true", help="Inspect cache contents"
1355
+ )
1356
+ cache_group.add_argument("--clear", action="store_true", help="Clear all cache")
1357
+ cache_group.add_argument(
1358
+ "--stats", action="store_true", help="Show cache performance statistics"
1359
+ )
1360
+ cache_parser.add_argument(
1361
+ "--verbose", "-v", action="store_true", help="Show detailed cache information"
1362
+ )
1363
+ cache_parser.add_argument(
1364
+ "--confirm",
1365
+ "-y",
1366
+ action="store_true",
1367
+ help="Skip confirmation for clear operation",
1368
+ )
1369
+
1370
+ # Performance debugging
1371
+ performance_parser = debug_subparsers.add_parser(
1372
+ "performance",
1373
+ help="Performance profiling and analysis",
1374
+ description="Profile operations and analyze bottlenecks",
1375
+ )
1376
+ perf_group = performance_parser.add_mutually_exclusive_group()
1377
+ perf_group.add_argument(
1378
+ "--profile",
1379
+ metavar="OPERATION",
1380
+ help="Profile specific operation (agent_load, service_init, cache_ops, memory_ops)",
1381
+ )
1382
+ perf_group.add_argument(
1383
+ "--benchmark", action="store_true", help="Run performance benchmarks"
1384
+ )
1385
+
1386
+ return debug_parser