claude-mpm 5.4.96__py3-none-any.whl → 5.6.17__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/agents/{CLAUDE_MPM_FOUNDERS_OUTPUT_STYLE.md → CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md} +14 -6
- claude_mpm/agents/PM_INSTRUCTIONS.md +44 -10
- claude_mpm/agents/WORKFLOW.md +2 -0
- claude_mpm/agents/templates/circuit-breakers.md +26 -17
- claude_mpm/cli/commands/autotodos.py +45 -5
- claude_mpm/cli/commands/commander.py +216 -0
- claude_mpm/cli/commands/hook_errors.py +60 -60
- claude_mpm/cli/commands/run.py +35 -3
- claude_mpm/cli/commands/skill_source.py +51 -2
- claude_mpm/cli/commands/skills.py +5 -3
- claude_mpm/cli/executor.py +32 -17
- claude_mpm/cli/parsers/base_parser.py +17 -0
- claude_mpm/cli/parsers/commander_parser.py +116 -0
- claude_mpm/cli/parsers/run_parser.py +10 -0
- claude_mpm/cli/parsers/skill_source_parser.py +4 -0
- claude_mpm/cli/parsers/skills_parser.py +5 -0
- claude_mpm/cli/startup.py +124 -3
- claude_mpm/cli/startup_display.py +2 -1
- claude_mpm/cli/utils.py +7 -3
- claude_mpm/commander/__init__.py +78 -0
- claude_mpm/commander/adapters/__init__.py +60 -0
- claude_mpm/commander/adapters/auggie.py +260 -0
- claude_mpm/commander/adapters/base.py +288 -0
- claude_mpm/commander/adapters/claude_code.py +392 -0
- claude_mpm/commander/adapters/codex.py +237 -0
- claude_mpm/commander/adapters/communication.py +366 -0
- claude_mpm/commander/adapters/example_usage.py +310 -0
- claude_mpm/commander/adapters/mpm.py +389 -0
- claude_mpm/commander/adapters/registry.py +204 -0
- claude_mpm/commander/api/__init__.py +16 -0
- claude_mpm/commander/api/app.py +121 -0
- claude_mpm/commander/api/errors.py +133 -0
- claude_mpm/commander/api/routes/__init__.py +8 -0
- claude_mpm/commander/api/routes/events.py +184 -0
- claude_mpm/commander/api/routes/inbox.py +171 -0
- claude_mpm/commander/api/routes/messages.py +148 -0
- claude_mpm/commander/api/routes/projects.py +271 -0
- claude_mpm/commander/api/routes/sessions.py +226 -0
- claude_mpm/commander/api/routes/work.py +296 -0
- claude_mpm/commander/api/schemas.py +186 -0
- claude_mpm/commander/chat/__init__.py +7 -0
- claude_mpm/commander/chat/cli.py +111 -0
- claude_mpm/commander/chat/commands.py +96 -0
- claude_mpm/commander/chat/repl.py +310 -0
- claude_mpm/commander/config.py +49 -0
- claude_mpm/commander/config_loader.py +115 -0
- claude_mpm/commander/core/__init__.py +10 -0
- claude_mpm/commander/core/block_manager.py +325 -0
- claude_mpm/commander/core/response_manager.py +323 -0
- claude_mpm/commander/daemon.py +594 -0
- claude_mpm/commander/env_loader.py +59 -0
- claude_mpm/commander/events/__init__.py +26 -0
- claude_mpm/commander/events/manager.py +332 -0
- claude_mpm/commander/frameworks/__init__.py +12 -0
- claude_mpm/commander/frameworks/base.py +143 -0
- claude_mpm/commander/frameworks/claude_code.py +58 -0
- claude_mpm/commander/frameworks/mpm.py +62 -0
- claude_mpm/commander/inbox/__init__.py +16 -0
- claude_mpm/commander/inbox/dedup.py +128 -0
- claude_mpm/commander/inbox/inbox.py +224 -0
- claude_mpm/commander/inbox/models.py +70 -0
- claude_mpm/commander/instance_manager.py +337 -0
- claude_mpm/commander/llm/__init__.py +6 -0
- claude_mpm/commander/llm/openrouter_client.py +167 -0
- claude_mpm/commander/llm/summarizer.py +70 -0
- claude_mpm/commander/memory/__init__.py +45 -0
- claude_mpm/commander/memory/compression.py +347 -0
- claude_mpm/commander/memory/embeddings.py +230 -0
- claude_mpm/commander/memory/entities.py +310 -0
- claude_mpm/commander/memory/example_usage.py +290 -0
- claude_mpm/commander/memory/integration.py +325 -0
- claude_mpm/commander/memory/search.py +381 -0
- claude_mpm/commander/memory/store.py +657 -0
- claude_mpm/commander/models/__init__.py +18 -0
- claude_mpm/commander/models/events.py +121 -0
- claude_mpm/commander/models/project.py +162 -0
- claude_mpm/commander/models/work.py +214 -0
- claude_mpm/commander/parsing/__init__.py +20 -0
- claude_mpm/commander/parsing/extractor.py +132 -0
- claude_mpm/commander/parsing/output_parser.py +270 -0
- claude_mpm/commander/parsing/patterns.py +100 -0
- claude_mpm/commander/persistence/__init__.py +11 -0
- claude_mpm/commander/persistence/event_store.py +274 -0
- claude_mpm/commander/persistence/state_store.py +309 -0
- claude_mpm/commander/persistence/work_store.py +164 -0
- claude_mpm/commander/polling/__init__.py +13 -0
- claude_mpm/commander/polling/event_detector.py +104 -0
- claude_mpm/commander/polling/output_buffer.py +49 -0
- claude_mpm/commander/polling/output_poller.py +153 -0
- claude_mpm/commander/project_session.py +268 -0
- claude_mpm/commander/proxy/__init__.py +12 -0
- claude_mpm/commander/proxy/formatter.py +89 -0
- claude_mpm/commander/proxy/output_handler.py +191 -0
- claude_mpm/commander/proxy/relay.py +155 -0
- claude_mpm/commander/registry.py +410 -0
- claude_mpm/commander/runtime/__init__.py +10 -0
- claude_mpm/commander/runtime/executor.py +191 -0
- claude_mpm/commander/runtime/monitor.py +346 -0
- claude_mpm/commander/session/__init__.py +6 -0
- claude_mpm/commander/session/context.py +81 -0
- claude_mpm/commander/session/manager.py +59 -0
- claude_mpm/commander/tmux_orchestrator.py +361 -0
- claude_mpm/commander/web/__init__.py +1 -0
- claude_mpm/commander/work/__init__.py +30 -0
- claude_mpm/commander/work/executor.py +207 -0
- claude_mpm/commander/work/queue.py +405 -0
- claude_mpm/commander/workflow/__init__.py +27 -0
- claude_mpm/commander/workflow/event_handler.py +241 -0
- claude_mpm/commander/workflow/notifier.py +146 -0
- claude_mpm/commands/mpm-config.md +8 -0
- claude_mpm/commands/mpm-doctor.md +8 -0
- claude_mpm/commands/mpm-help.md +8 -0
- claude_mpm/commands/mpm-init.md +8 -0
- claude_mpm/commands/mpm-monitor.md +8 -0
- claude_mpm/commands/mpm-organize.md +8 -0
- claude_mpm/commands/mpm-postmortem.md +8 -0
- claude_mpm/commands/mpm-session-resume.md +8 -0
- claude_mpm/commands/mpm-status.md +8 -0
- claude_mpm/commands/mpm-ticket-view.md +8 -0
- claude_mpm/commands/mpm-version.md +8 -0
- claude_mpm/commands/mpm.md +8 -0
- claude_mpm/config/agent_presets.py +8 -7
- claude_mpm/config/skill_sources.py +16 -0
- claude_mpm/core/claude_runner.py +143 -0
- claude_mpm/core/config.py +32 -19
- claude_mpm/core/logger.py +26 -9
- claude_mpm/core/logging_utils.py +35 -11
- claude_mpm/core/output_style_manager.py +49 -12
- claude_mpm/core/unified_config.py +10 -6
- claude_mpm/core/unified_paths.py +68 -80
- claude_mpm/experimental/cli_enhancements.py +2 -1
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/auto_pause_handler.py +29 -30
- claude_mpm/hooks/claude_hooks/event_handlers.py +112 -99
- claude_mpm/hooks/claude_hooks/hook_handler.py +81 -88
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
- claude_mpm/hooks/claude_hooks/installer.py +116 -8
- claude_mpm/hooks/claude_hooks/memory_integration.py +51 -31
- claude_mpm/hooks/claude_hooks/response_tracking.py +39 -58
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-314.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +23 -28
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +36 -103
- claude_mpm/hooks/claude_hooks/services/state_manager.py +23 -36
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +47 -73
- claude_mpm/hooks/session_resume_hook.py +22 -18
- claude_mpm/hooks/templates/pre_tool_use_template.py +10 -2
- claude_mpm/scripts/claude-hook-handler.sh +43 -16
- claude_mpm/scripts/start_activity_logging.py +0 -0
- claude_mpm/services/agents/agent_recommendation_service.py +8 -8
- claude_mpm/services/agents/agent_selection_service.py +2 -2
- claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
- claude_mpm/services/agents/single_tier_deployment_service.py +4 -4
- claude_mpm/services/event_log.py +8 -0
- claude_mpm/services/pm_skills_deployer.py +84 -6
- claude_mpm/services/skills/git_skill_source_manager.py +130 -10
- claude_mpm/services/skills/selective_skill_deployer.py +28 -0
- claude_mpm/services/skills/skill_discovery_service.py +74 -4
- claude_mpm/services/skills_deployer.py +31 -5
- claude_mpm/skills/__init__.py +2 -1
- claude_mpm/skills/bundled/pm/mpm/SKILL.md +38 -0
- claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
- claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
- claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
- claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
- claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
- claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
- claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
- claude_mpm/skills/bundled/pm/mpm-session-pause/SKILL.md +170 -0
- claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
- claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
- claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
- claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
- claude_mpm/skills/registry.py +295 -90
- {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.17.dist-info}/METADATA +22 -6
- {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.17.dist-info}/RECORD +213 -83
- {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.17.dist-info}/WHEEL +0 -0
- {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.17.dist-info}/entry_points.txt +0 -0
- {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.17.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.17.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.96.dist-info → claude_mpm-5.6.17.dist-info}/top_level.txt +0 -0
|
@@ -57,33 +57,33 @@ def list_errors(format, hook_type):
|
|
|
57
57
|
|
|
58
58
|
if not errors:
|
|
59
59
|
if hook_type:
|
|
60
|
-
click.echo(f"No errors recorded for hook type: {hook_type}")
|
|
60
|
+
click.echo(f"No errors recorded for hook type: {hook_type}", err=True)
|
|
61
61
|
else:
|
|
62
|
-
click.echo("No errors recorded. Hook system is healthy! ✅")
|
|
62
|
+
click.echo("No errors recorded. Hook system is healthy! ✅", err=True)
|
|
63
63
|
return
|
|
64
64
|
|
|
65
65
|
if format == "json":
|
|
66
66
|
# JSON output
|
|
67
|
-
click.echo(json.dumps(errors, indent=2))
|
|
67
|
+
click.echo(json.dumps(errors, indent=2), err=True)
|
|
68
68
|
else:
|
|
69
69
|
# Table output
|
|
70
|
-
click.echo("\n" + "=" * 80)
|
|
71
|
-
click.echo("Hook Error Memory Report")
|
|
72
|
-
click.echo("=" * 80)
|
|
70
|
+
click.echo("\n" + "=" * 80, err=True)
|
|
71
|
+
click.echo("Hook Error Memory Report", err=True)
|
|
72
|
+
click.echo("=" * 80, err=True)
|
|
73
73
|
|
|
74
74
|
for key, data in errors.items():
|
|
75
|
-
click.echo(f"\n🔴 Error: {data['type']}")
|
|
76
|
-
click.echo(f" Hook Type: {data['hook_type']}")
|
|
77
|
-
click.echo(f" Details: {data['details']}")
|
|
78
|
-
click.echo(f" Match: {data['match']}")
|
|
79
|
-
click.echo(f" Count: {data['count']} occurrences")
|
|
80
|
-
click.echo(f" First Seen: {data['first_seen']}")
|
|
81
|
-
click.echo(f" Last Seen: {data['last_seen']}")
|
|
75
|
+
click.echo(f"\n🔴 Error: {data['type']}", err=True)
|
|
76
|
+
click.echo(f" Hook Type: {data['hook_type']}", err=True)
|
|
77
|
+
click.echo(f" Details: {data['details']}", err=True)
|
|
78
|
+
click.echo(f" Match: {data['match']}", err=True)
|
|
79
|
+
click.echo(f" Count: {data['count']} occurrences", err=True)
|
|
80
|
+
click.echo(f" First Seen: {data['first_seen']}", err=True)
|
|
81
|
+
click.echo(f" Last Seen: {data['last_seen']}", err=True)
|
|
82
82
|
|
|
83
|
-
click.echo("\n" + "=" * 80)
|
|
84
|
-
click.echo(f"Total unique errors: {len(errors)}")
|
|
85
|
-
click.echo(f"Memory file: {error_memory.memory_file}")
|
|
86
|
-
click.echo("\nTo clear errors: claude-mpm hook-errors clear")
|
|
83
|
+
click.echo("\n" + "=" * 80, err=True)
|
|
84
|
+
click.echo(f"Total unique errors: {len(errors)}", err=True)
|
|
85
|
+
click.echo(f"Memory file: {error_memory.memory_file}", err=True)
|
|
86
|
+
click.echo("\nTo clear errors: claude-mpm hook-errors clear", err=True)
|
|
87
87
|
|
|
88
88
|
|
|
89
89
|
@hook_errors_group.command(name="summary")
|
|
@@ -99,28 +99,28 @@ def show_summary():
|
|
|
99
99
|
summary = error_memory.get_error_summary()
|
|
100
100
|
|
|
101
101
|
if summary["total_errors"] == 0:
|
|
102
|
-
click.echo("No errors recorded. Hook system is healthy! ✅")
|
|
102
|
+
click.echo("No errors recorded. Hook system is healthy! ✅", err=True)
|
|
103
103
|
return
|
|
104
104
|
|
|
105
|
-
click.echo("\n" + "=" * 80)
|
|
106
|
-
click.echo("Hook Error Summary")
|
|
107
|
-
click.echo("=" * 80)
|
|
108
|
-
click.echo("\n📊 Statistics:")
|
|
109
|
-
click.echo(f" Total Errors: {summary['total_errors']}")
|
|
110
|
-
click.echo(f" Unique Errors: {summary['unique_errors']}")
|
|
105
|
+
click.echo("\n" + "=" * 80, err=True)
|
|
106
|
+
click.echo("Hook Error Summary", err=True)
|
|
107
|
+
click.echo("=" * 80, err=True)
|
|
108
|
+
click.echo("\n📊 Statistics:", err=True)
|
|
109
|
+
click.echo(f" Total Errors: {summary['total_errors']}", err=True)
|
|
110
|
+
click.echo(f" Unique Errors: {summary['unique_errors']}", err=True)
|
|
111
111
|
|
|
112
112
|
if summary["errors_by_type"]:
|
|
113
|
-
click.echo("\n🔍 Errors by Type:")
|
|
113
|
+
click.echo("\n🔍 Errors by Type:", err=True)
|
|
114
114
|
for error_type, count in summary["errors_by_type"].items():
|
|
115
|
-
click.echo(f" {error_type}: {count}")
|
|
115
|
+
click.echo(f" {error_type}: {count}", err=True)
|
|
116
116
|
|
|
117
117
|
if summary["errors_by_hook"]:
|
|
118
|
-
click.echo("\n🎣 Errors by Hook Type:")
|
|
118
|
+
click.echo("\n🎣 Errors by Hook Type:", err=True)
|
|
119
119
|
for hook_type, count in summary["errors_by_hook"].items():
|
|
120
|
-
click.echo(f" {hook_type}: {count}")
|
|
120
|
+
click.echo(f" {hook_type}: {count}", err=True)
|
|
121
121
|
|
|
122
|
-
click.echo(f"\n📁 Memory File: {summary['memory_file']}")
|
|
123
|
-
click.echo("\nFor detailed list: claude-mpm hook-errors list")
|
|
122
|
+
click.echo(f"\n📁 Memory File: {summary['memory_file']}", err=True)
|
|
123
|
+
click.echo("\nFor detailed list: claude-mpm hook-errors list", err=True)
|
|
124
124
|
|
|
125
125
|
|
|
126
126
|
@hook_errors_group.command(name="clear")
|
|
@@ -158,21 +158,21 @@ def clear_errors(hook_type, yes):
|
|
|
158
158
|
scope = "all hook types"
|
|
159
159
|
|
|
160
160
|
if count == 0:
|
|
161
|
-
click.echo(f"No errors to clear {scope}.")
|
|
161
|
+
click.echo(f"No errors to clear {scope}.", err=True)
|
|
162
162
|
return
|
|
163
163
|
|
|
164
164
|
# Confirm if not using -y flag
|
|
165
165
|
if not yes:
|
|
166
166
|
message = f"Clear {count} error(s) {scope}?"
|
|
167
167
|
if not click.confirm(message):
|
|
168
|
-
click.echo("Cancelled.")
|
|
168
|
+
click.echo("Cancelled.", err=True)
|
|
169
169
|
return
|
|
170
170
|
|
|
171
171
|
# Clear errors
|
|
172
172
|
error_memory.clear_errors(hook_type)
|
|
173
173
|
|
|
174
|
-
click.echo(f"✅ Cleared {count} error(s) {scope}.")
|
|
175
|
-
click.echo("\nHooks will be retried on next execution.")
|
|
174
|
+
click.echo(f"✅ Cleared {count} error(s) {scope}.", err=True)
|
|
175
|
+
click.echo("\nHooks will be retried on next execution.", err=True)
|
|
176
176
|
|
|
177
177
|
|
|
178
178
|
@hook_errors_group.command(name="diagnose")
|
|
@@ -201,19 +201,19 @@ def diagnose_errors(hook_type):
|
|
|
201
201
|
|
|
202
202
|
if not errors:
|
|
203
203
|
if hook_type:
|
|
204
|
-
click.echo(f"No errors to diagnose for hook type: {hook_type}")
|
|
204
|
+
click.echo(f"No errors to diagnose for hook type: {hook_type}", err=True)
|
|
205
205
|
else:
|
|
206
|
-
click.echo("No errors to diagnose. Hook system is healthy! ✅")
|
|
206
|
+
click.echo("No errors to diagnose. Hook system is healthy! ✅", err=True)
|
|
207
207
|
return
|
|
208
208
|
|
|
209
|
-
click.echo("\n" + "=" * 80)
|
|
210
|
-
click.echo("Hook Error Diagnostics")
|
|
211
|
-
click.echo("=" * 80)
|
|
209
|
+
click.echo("\n" + "=" * 80, err=True)
|
|
210
|
+
click.echo("Hook Error Diagnostics", err=True)
|
|
211
|
+
click.echo("=" * 80, err=True)
|
|
212
212
|
|
|
213
213
|
for key, data in errors.items():
|
|
214
|
-
click.echo(f"\n🔴 Error: {data['type']}")
|
|
215
|
-
click.echo(f" Hook: {data['hook_type']}")
|
|
216
|
-
click.echo(f" Count: {data['count']} failures")
|
|
214
|
+
click.echo(f"\n🔴 Error: {data['type']}", err=True)
|
|
215
|
+
click.echo(f" Hook: {data['hook_type']}", err=True)
|
|
216
|
+
click.echo(f" Count: {data['count']} failures", err=True)
|
|
217
217
|
|
|
218
218
|
# Generate and show fix suggestion
|
|
219
219
|
error_info = {
|
|
@@ -223,13 +223,13 @@ def diagnose_errors(hook_type):
|
|
|
223
223
|
}
|
|
224
224
|
suggestion = error_memory.suggest_fix(error_info)
|
|
225
225
|
|
|
226
|
-
click.echo("\n" + "-" * 80)
|
|
227
|
-
click.echo(suggestion)
|
|
228
|
-
click.echo("-" * 80)
|
|
226
|
+
click.echo("\n" + "-" * 80, err=True)
|
|
227
|
+
click.echo(suggestion, err=True)
|
|
228
|
+
click.echo("-" * 80, err=True)
|
|
229
229
|
|
|
230
|
-
click.echo("\n" + "=" * 80)
|
|
231
|
-
click.echo("After fixing issues, clear errors to retry:")
|
|
232
|
-
click.echo(" claude-mpm hook-errors clear")
|
|
230
|
+
click.echo("\n" + "=" * 80, err=True)
|
|
231
|
+
click.echo("After fixing issues, clear errors to retry:", err=True)
|
|
232
|
+
click.echo(" claude-mpm hook-errors clear", err=True)
|
|
233
233
|
|
|
234
234
|
|
|
235
235
|
@hook_errors_group.command(name="status")
|
|
@@ -244,27 +244,27 @@ def show_status():
|
|
|
244
244
|
error_memory = get_hook_error_memory()
|
|
245
245
|
summary = error_memory.get_error_summary()
|
|
246
246
|
|
|
247
|
-
click.echo("\n📊 Hook Error Memory Status")
|
|
248
|
-
click.echo("=" * 80)
|
|
247
|
+
click.echo("\n📊 Hook Error Memory Status", err=True)
|
|
248
|
+
click.echo("=" * 80, err=True)
|
|
249
249
|
|
|
250
250
|
if summary["total_errors"] == 0:
|
|
251
|
-
click.echo("✅ Status: Healthy (no errors recorded)")
|
|
251
|
+
click.echo("✅ Status: Healthy (no errors recorded)", err=True)
|
|
252
252
|
else:
|
|
253
|
-
click.echo(f"⚠️ Status: {summary['total_errors']} error(s) recorded")
|
|
254
|
-
click.echo(f" Unique errors: {summary['unique_errors']}")
|
|
253
|
+
click.echo(f"⚠️ Status: {summary['total_errors']} error(s) recorded", err=True)
|
|
254
|
+
click.echo(f" Unique errors: {summary['unique_errors']}", err=True)
|
|
255
255
|
|
|
256
256
|
# Show which hooks are affected
|
|
257
257
|
if summary["errors_by_hook"]:
|
|
258
258
|
affected_hooks = list(summary["errors_by_hook"].keys())
|
|
259
|
-
click.echo(f" Affected hooks: {', '.join(affected_hooks)}")
|
|
259
|
+
click.echo(f" Affected hooks: {', '.join(affected_hooks)}", err=True)
|
|
260
260
|
|
|
261
|
-
click.echo(f"\n📁 Memory file: {summary['memory_file']}")
|
|
262
|
-
click.echo(f" Exists: {Path(summary['memory_file']).exists()}")
|
|
261
|
+
click.echo(f"\n📁 Memory file: {summary['memory_file']}", err=True)
|
|
262
|
+
click.echo(f" Exists: {Path(summary['memory_file']).exists()}", err=True)
|
|
263
263
|
|
|
264
|
-
click.echo("\nCommands:")
|
|
265
|
-
click.echo(" claude-mpm hook-errors list # View detailed errors")
|
|
266
|
-
click.echo(" claude-mpm hook-errors diagnose # Get fix suggestions")
|
|
267
|
-
click.echo(" claude-mpm hook-errors clear # Clear and retry")
|
|
264
|
+
click.echo("\nCommands:", err=True)
|
|
265
|
+
click.echo(" claude-mpm hook-errors list # View detailed errors", err=True)
|
|
266
|
+
click.echo(" claude-mpm hook-errors diagnose # Get fix suggestions", err=True)
|
|
267
|
+
click.echo(" claude-mpm hook-errors clear # Clear and retry", err=True)
|
|
268
268
|
|
|
269
269
|
|
|
270
270
|
# Register the command group
|
claude_mpm/cli/commands/run.py
CHANGED
|
@@ -13,7 +13,7 @@ DESIGN DECISIONS:
|
|
|
13
13
|
- Support multiple output formats (json, yaml, table, text)
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
|
-
import subprocess
|
|
16
|
+
import subprocess # nosec B404 - required for process management
|
|
17
17
|
import sys
|
|
18
18
|
from datetime import datetime, timezone
|
|
19
19
|
from typing import Optional
|
|
@@ -489,6 +489,18 @@ class RunCommand(BaseCommand):
|
|
|
489
489
|
if hasattr(args, "claude_args") and args.claude_args:
|
|
490
490
|
claude_args.extend(args.claude_args)
|
|
491
491
|
|
|
492
|
+
# Add --resume if flag is set
|
|
493
|
+
if getattr(args, "resume", False) and "--resume" not in claude_args:
|
|
494
|
+
claude_args.insert(0, "--resume")
|
|
495
|
+
|
|
496
|
+
# Add --chrome if flag is set
|
|
497
|
+
if getattr(args, "chrome", False) and "--chrome" not in claude_args:
|
|
498
|
+
claude_args.insert(0, "--chrome")
|
|
499
|
+
|
|
500
|
+
# Add --no-chrome if flag is set
|
|
501
|
+
if getattr(args, "no_chrome", False) and "--no-chrome" not in claude_args:
|
|
502
|
+
claude_args.insert(0, "--no-chrome")
|
|
503
|
+
|
|
492
504
|
# Create runner
|
|
493
505
|
runner = ClaudeRunner(
|
|
494
506
|
enable_tickets=enable_tickets,
|
|
@@ -553,7 +565,7 @@ class RunCommand(BaseCommand):
|
|
|
553
565
|
wrapper_path = get_scripts_dir() / "interactive_wrapper.py"
|
|
554
566
|
if wrapper_path.exists():
|
|
555
567
|
print("Starting interactive session with command interception...")
|
|
556
|
-
subprocess.run([sys.executable, str(wrapper_path)], check=False)
|
|
568
|
+
subprocess.run([sys.executable, str(wrapper_path)], check=False) # nosec B603 - trusted internal paths
|
|
557
569
|
else:
|
|
558
570
|
self.logger.warning(
|
|
559
571
|
"Interactive wrapper not found, falling back to normal mode"
|
|
@@ -907,6 +919,26 @@ def run_session_legacy(args):
|
|
|
907
919
|
else:
|
|
908
920
|
logger.info("[INFO]️ --resume already in claude_args")
|
|
909
921
|
|
|
922
|
+
# Add --chrome to claude_args if the flag is set
|
|
923
|
+
chrome_flag_present = getattr(args, "chrome", False)
|
|
924
|
+
if chrome_flag_present:
|
|
925
|
+
logger.info("📌 --chrome flag detected in args")
|
|
926
|
+
if "--chrome" not in raw_claude_args:
|
|
927
|
+
raw_claude_args = ["--chrome", *raw_claude_args]
|
|
928
|
+
logger.info("✅ Added --chrome to claude_args")
|
|
929
|
+
else:
|
|
930
|
+
logger.info("ℹ️ --chrome already in claude_args")
|
|
931
|
+
|
|
932
|
+
# Add --no-chrome to claude_args if the flag is set
|
|
933
|
+
no_chrome_flag_present = getattr(args, "no_chrome", False)
|
|
934
|
+
if no_chrome_flag_present:
|
|
935
|
+
logger.info("📌 --no-chrome flag detected in args")
|
|
936
|
+
if "--no-chrome" not in raw_claude_args:
|
|
937
|
+
raw_claude_args = ["--no-chrome", *raw_claude_args]
|
|
938
|
+
logger.info("✅ Added --no-chrome to claude_args")
|
|
939
|
+
else:
|
|
940
|
+
logger.info("ℹ️ --no-chrome already in claude_args")
|
|
941
|
+
|
|
910
942
|
# Filter out claude-mpm specific flags before passing to Claude CLI
|
|
911
943
|
logger.debug(f"Pre-filter claude_args: {raw_claude_args}")
|
|
912
944
|
claude_args = filter_claude_mpm_args(raw_claude_args)
|
|
@@ -1044,7 +1076,7 @@ def run_session_legacy(args):
|
|
|
1044
1076
|
wrapper_path = get_scripts_dir() / "interactive_wrapper.py"
|
|
1045
1077
|
if wrapper_path.exists():
|
|
1046
1078
|
print("Starting interactive session with command interception...")
|
|
1047
|
-
subprocess.run([sys.executable, str(wrapper_path)], check=False)
|
|
1079
|
+
subprocess.run([sys.executable, str(wrapper_path)], check=False) # nosec B603 - trusted internal paths
|
|
1048
1080
|
else:
|
|
1049
1081
|
logger.warning("Interactive wrapper not found, falling back to normal mode")
|
|
1050
1082
|
runner.run_interactive(context)
|
|
@@ -11,6 +11,7 @@ for better UX. Handles errors gracefully with actionable messages.
|
|
|
11
11
|
|
|
12
12
|
import json
|
|
13
13
|
import logging
|
|
14
|
+
import os
|
|
14
15
|
import re
|
|
15
16
|
|
|
16
17
|
from ...config.skill_sources import SkillSource, SkillSourceConfiguration
|
|
@@ -20,6 +21,33 @@ from ...services.skills.skill_discovery_service import SkillDiscoveryService
|
|
|
20
21
|
logger = logging.getLogger(__name__)
|
|
21
22
|
|
|
22
23
|
|
|
24
|
+
def _get_github_token(source: SkillSource | None = None) -> str | None:
|
|
25
|
+
"""Get GitHub token with source-specific override support.
|
|
26
|
+
|
|
27
|
+
Priority: source.token > GITHUB_TOKEN > GH_TOKEN
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
source: Optional SkillSource to check for per-source token
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
GitHub token if found, None otherwise
|
|
34
|
+
|
|
35
|
+
Security Note:
|
|
36
|
+
Token is never logged or printed to avoid exposure.
|
|
37
|
+
"""
|
|
38
|
+
# Priority 1: Per-source token (env var reference or direct)
|
|
39
|
+
if source and source.token:
|
|
40
|
+
if source.token.startswith("$"):
|
|
41
|
+
# Env var reference: $VAR_NAME -> os.environ.get("VAR_NAME")
|
|
42
|
+
env_var_name = source.token[1:]
|
|
43
|
+
return os.environ.get(env_var_name)
|
|
44
|
+
# Direct token (not recommended but supported)
|
|
45
|
+
return source.token
|
|
46
|
+
|
|
47
|
+
# Priority 2-3: Global environment variables
|
|
48
|
+
return os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN")
|
|
49
|
+
|
|
50
|
+
|
|
23
51
|
def _test_skill_repository_access(source: SkillSource) -> dict:
|
|
24
52
|
"""Test if skill repository is accessible via GitHub API.
|
|
25
53
|
|
|
@@ -58,7 +86,13 @@ def _test_skill_repository_access(source: SkillSource) -> dict:
|
|
|
58
86
|
# Test GitHub API access
|
|
59
87
|
api_url = f"https://api.github.com/repos/{owner_repo}"
|
|
60
88
|
|
|
61
|
-
|
|
89
|
+
# Build headers with authentication if token available
|
|
90
|
+
headers = {"Accept": "application/vnd.github+json"}
|
|
91
|
+
token = _get_github_token(source)
|
|
92
|
+
if token:
|
|
93
|
+
headers["Authorization"] = f"token {token}"
|
|
94
|
+
|
|
95
|
+
response = requests.get(api_url, headers=headers, timeout=10)
|
|
62
96
|
|
|
63
97
|
if response.status_code == 200:
|
|
64
98
|
return {"accessible": True, "error": None}
|
|
@@ -68,9 +102,14 @@ def _test_skill_repository_access(source: SkillSource) -> dict:
|
|
|
68
102
|
"error": f"Repository not found: {owner_repo}",
|
|
69
103
|
}
|
|
70
104
|
if response.status_code == 403:
|
|
105
|
+
error_msg = "Access denied (private repository or rate limit)"
|
|
106
|
+
if not token:
|
|
107
|
+
error_msg += (
|
|
108
|
+
". Try setting GITHUB_TOKEN environment variable for private repos"
|
|
109
|
+
)
|
|
71
110
|
return {
|
|
72
111
|
"accessible": False,
|
|
73
|
-
"error":
|
|
112
|
+
"error": error_msg,
|
|
74
113
|
}
|
|
75
114
|
return {
|
|
76
115
|
"accessible": False,
|
|
@@ -263,6 +302,15 @@ def handle_add_skill_source(args) -> int:
|
|
|
263
302
|
|
|
264
303
|
# Create new source
|
|
265
304
|
enabled = not args.disabled
|
|
305
|
+
token = getattr(args, "token", None)
|
|
306
|
+
|
|
307
|
+
# Security warning for direct tokens
|
|
308
|
+
if token and not token.startswith("$"):
|
|
309
|
+
print("⚠️ Warning: Direct token values in config are not recommended")
|
|
310
|
+
print(" Consider using environment variable reference instead:")
|
|
311
|
+
print(" --token $MY_PRIVATE_TOKEN")
|
|
312
|
+
print()
|
|
313
|
+
|
|
266
314
|
source = SkillSource(
|
|
267
315
|
id=source_id,
|
|
268
316
|
type="git",
|
|
@@ -270,6 +318,7 @@ def handle_add_skill_source(args) -> int:
|
|
|
270
318
|
branch=args.branch,
|
|
271
319
|
priority=args.priority,
|
|
272
320
|
enabled=enabled,
|
|
321
|
+
token=token,
|
|
273
322
|
)
|
|
274
323
|
|
|
275
324
|
# Determine if we should test
|
|
@@ -538,6 +538,7 @@ class SkillsManagementCommand(BaseCommand):
|
|
|
538
538
|
toolchain = getattr(args, "toolchain", None)
|
|
539
539
|
categories = getattr(args, "categories", None)
|
|
540
540
|
force = getattr(args, "force", False)
|
|
541
|
+
deploy_all = getattr(args, "all", False)
|
|
541
542
|
|
|
542
543
|
if collection:
|
|
543
544
|
console.print(
|
|
@@ -548,14 +549,15 @@ class SkillsManagementCommand(BaseCommand):
|
|
|
548
549
|
"\n[bold cyan]Deploying skills from default collection...[/bold cyan]\n"
|
|
549
550
|
)
|
|
550
551
|
|
|
551
|
-
#
|
|
552
|
-
#
|
|
552
|
+
# Use selective deployment unless --all flag is provided
|
|
553
|
+
# Selective mode deploys only agent-referenced skills
|
|
554
|
+
# --all mode deploys all available skills from the collection
|
|
553
555
|
result = self.skills_deployer.deploy_skills(
|
|
554
556
|
collection=collection,
|
|
555
557
|
toolchain=toolchain,
|
|
556
558
|
categories=categories,
|
|
557
559
|
force=force,
|
|
558
|
-
selective=
|
|
560
|
+
selective=not deploy_all,
|
|
559
561
|
)
|
|
560
562
|
|
|
561
563
|
# Display results
|
claude_mpm/cli/executor.py
CHANGED
|
@@ -127,6 +127,14 @@ def execute_command(command: str, args) -> int:
|
|
|
127
127
|
result = handle_verify(args)
|
|
128
128
|
return result if result is not None else 0
|
|
129
129
|
|
|
130
|
+
# Handle commander command with lazy import
|
|
131
|
+
if command == "commander":
|
|
132
|
+
# Lazy import to avoid loading unless needed
|
|
133
|
+
from .commands.commander import handle_commander_command
|
|
134
|
+
|
|
135
|
+
result = handle_commander_command(args)
|
|
136
|
+
return result if result is not None else 0
|
|
137
|
+
|
|
130
138
|
# Handle skill-source command with lazy import
|
|
131
139
|
if command == "skill-source":
|
|
132
140
|
# Lazy import to avoid loading unless needed
|
|
@@ -206,27 +214,33 @@ def execute_command(command: str, args) -> int:
|
|
|
206
214
|
"status": show_status,
|
|
207
215
|
}
|
|
208
216
|
|
|
209
|
-
# Get handler and
|
|
217
|
+
# Get handler and call it with argument list (same pattern as autotodos)
|
|
210
218
|
handler = handlers.get(subcommand)
|
|
211
219
|
if handler:
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
ctx = click.Context(command=handler)
|
|
220
|
+
try:
|
|
221
|
+
# Build argument list for Click command based on subcommand
|
|
222
|
+
click_args = []
|
|
216
223
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
224
|
+
# list command: --format, --hook-type
|
|
225
|
+
if subcommand == "list":
|
|
226
|
+
if hasattr(args, "format") and args.format:
|
|
227
|
+
click_args.extend(["--format", args.format])
|
|
228
|
+
if hasattr(args, "hook_type") and args.hook_type:
|
|
229
|
+
click_args.extend(["--hook-type", args.hook_type])
|
|
230
|
+
# clear command: --hook-type, -y
|
|
231
|
+
elif subcommand == "clear":
|
|
232
|
+
if hasattr(args, "hook_type") and args.hook_type:
|
|
233
|
+
click_args.extend(["--hook-type", args.hook_type])
|
|
234
|
+
if hasattr(args, "yes") and args.yes:
|
|
235
|
+
click_args.append("-y")
|
|
236
|
+
# diagnose command: hook_type (positional argument)
|
|
237
|
+
elif subcommand == "diagnose":
|
|
238
|
+
if hasattr(args, "hook_type") and args.hook_type:
|
|
239
|
+
click_args.append(args.hook_type)
|
|
240
|
+
# status and summary commands: no options
|
|
225
241
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
with ctx:
|
|
229
|
-
handler.invoke(ctx, **kwargs)
|
|
242
|
+
# Call Click command with argument list and standalone_mode=False
|
|
243
|
+
handler(click_args, standalone_mode=False)
|
|
230
244
|
return 0
|
|
231
245
|
except SystemExit as e:
|
|
232
246
|
return e.code if e.code is not None else 0
|
|
@@ -346,6 +360,7 @@ def execute_command(command: str, args) -> int:
|
|
|
346
360
|
CLICommands.SKILLS.value: manage_skills,
|
|
347
361
|
"debug": manage_debug, # Add debug command
|
|
348
362
|
"mpm-init": None, # Will be handled separately with lazy import
|
|
363
|
+
"commander": None, # Will be handled separately with lazy import
|
|
349
364
|
}
|
|
350
365
|
|
|
351
366
|
# Execute command if found
|
|
@@ -297,6 +297,16 @@ def add_top_level_run_arguments(parser: argparse.ArgumentParser) -> None:
|
|
|
297
297
|
action="store_true",
|
|
298
298
|
help="Force refresh agents and skills from remote repos, bypassing ETag cache",
|
|
299
299
|
)
|
|
300
|
+
run_group.add_argument(
|
|
301
|
+
"--chrome",
|
|
302
|
+
action="store_true",
|
|
303
|
+
help="Enable Claude in Chrome integration (passed to Claude Code)",
|
|
304
|
+
)
|
|
305
|
+
run_group.add_argument(
|
|
306
|
+
"--no-chrome",
|
|
307
|
+
action="store_true",
|
|
308
|
+
help="Disable Claude in Chrome integration (passed to Claude Code)",
|
|
309
|
+
)
|
|
300
310
|
|
|
301
311
|
# Dependency checking options (for backward compatibility at top level)
|
|
302
312
|
dep_group_top = parser.add_argument_group(
|
|
@@ -492,6 +502,13 @@ def create_parser(
|
|
|
492
502
|
except ImportError:
|
|
493
503
|
pass
|
|
494
504
|
|
|
505
|
+
try:
|
|
506
|
+
from .commander_parser import add_commander_subparser
|
|
507
|
+
|
|
508
|
+
add_commander_subparser(subparsers)
|
|
509
|
+
except ImportError:
|
|
510
|
+
pass
|
|
511
|
+
|
|
495
512
|
# Add uninstall command parser
|
|
496
513
|
try:
|
|
497
514
|
from ..commands.uninstall import add_uninstall_parser
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Commander parser module for claude-mpm CLI.
|
|
3
|
+
|
|
4
|
+
WHY: This module provides the commander subcommand for interactive instance management
|
|
5
|
+
and chat interface.
|
|
6
|
+
|
|
7
|
+
DESIGN DECISION: Uses subparser pattern consistent with other commands (run, agents, etc.)
|
|
8
|
+
to provide a clean interface for Commander mode.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def add_commander_subparser(subparsers: argparse._SubParsersAction) -> None:
|
|
16
|
+
"""
|
|
17
|
+
Add commander subcommand parser.
|
|
18
|
+
|
|
19
|
+
WHY: Provides interactive mode for managing and chatting with multiple Claude instances.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
subparsers: The subparsers object to add the commander parser to
|
|
23
|
+
"""
|
|
24
|
+
commander_parser = subparsers.add_parser(
|
|
25
|
+
"commander",
|
|
26
|
+
help="Launch Commander multi-project orchestration (ALPHA)",
|
|
27
|
+
description="""
|
|
28
|
+
Commander Mode - Multi-Project Orchestration (ALPHA)
|
|
29
|
+
|
|
30
|
+
The commander subcommand auto-starts the Commander daemon (if not already running)
|
|
31
|
+
and launches an interactive REPL for managing multiple Claude Code instances.
|
|
32
|
+
|
|
33
|
+
Commander provides:
|
|
34
|
+
- Auto-starting daemon that manages project lifecycles
|
|
35
|
+
- Interactive REPL for controlling instances
|
|
36
|
+
- Tmux-based session management
|
|
37
|
+
- Real-time output monitoring
|
|
38
|
+
- REST API for external control (http://127.0.0.1:8765)
|
|
39
|
+
|
|
40
|
+
REPL Commands:
|
|
41
|
+
list, ls, instances List active instances
|
|
42
|
+
start <path> Start new instance at path
|
|
43
|
+
--framework <cc|mpm> Specify framework (default: cc)
|
|
44
|
+
--name <name> Specify instance name (default: dir name)
|
|
45
|
+
stop <name> Stop an instance
|
|
46
|
+
connect <name> Connect to an instance
|
|
47
|
+
disconnect Disconnect from current instance
|
|
48
|
+
status Show current session status
|
|
49
|
+
help Show help message
|
|
50
|
+
exit, quit, q Exit Commander
|
|
51
|
+
|
|
52
|
+
Natural Language:
|
|
53
|
+
When connected to an instance, any input that is not a built-in
|
|
54
|
+
command will be sent to the connected instance as a message.
|
|
55
|
+
|
|
56
|
+
Examples:
|
|
57
|
+
# Start daemon and launch interactive chat
|
|
58
|
+
claude-mpm commander
|
|
59
|
+
|
|
60
|
+
# Start daemon only (no chat interface)
|
|
61
|
+
claude-mpm commander --daemon-only
|
|
62
|
+
|
|
63
|
+
# Use custom port
|
|
64
|
+
claude-mpm commander --port 9000
|
|
65
|
+
|
|
66
|
+
# In REPL:
|
|
67
|
+
> start ~/myproject --framework cc --name myapp
|
|
68
|
+
> connect myapp
|
|
69
|
+
> Fix the authentication bug in login.py
|
|
70
|
+
> disconnect
|
|
71
|
+
> exit
|
|
72
|
+
""",
|
|
73
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Optional: Port for internal services
|
|
77
|
+
commander_parser.add_argument(
|
|
78
|
+
"--port",
|
|
79
|
+
type=int,
|
|
80
|
+
default=8765,
|
|
81
|
+
help="Port for internal services (default: 8765)",
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# Optional: State directory
|
|
85
|
+
commander_parser.add_argument(
|
|
86
|
+
"--state-dir",
|
|
87
|
+
type=Path,
|
|
88
|
+
help="Directory for state persistence (optional)",
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
# Debug mode
|
|
92
|
+
commander_parser.add_argument(
|
|
93
|
+
"--debug",
|
|
94
|
+
action="store_true",
|
|
95
|
+
help="Enable debug logging",
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
# Daemon auto-start options
|
|
99
|
+
commander_parser.add_argument(
|
|
100
|
+
"--host",
|
|
101
|
+
type=str,
|
|
102
|
+
default="127.0.0.1",
|
|
103
|
+
help="Daemon host (default: 127.0.0.1)",
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
commander_parser.add_argument(
|
|
107
|
+
"--no-chat",
|
|
108
|
+
action="store_true",
|
|
109
|
+
help="Start daemon only without interactive chat",
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
commander_parser.add_argument(
|
|
113
|
+
"--daemon-only",
|
|
114
|
+
action="store_true",
|
|
115
|
+
help="Alias for --no-chat (start daemon only)",
|
|
116
|
+
)
|
|
@@ -85,6 +85,16 @@ def add_run_arguments(parser: argparse.ArgumentParser) -> None:
|
|
|
85
85
|
action="store_true",
|
|
86
86
|
help="Pass --resume flag to Claude Code to resume the last conversation",
|
|
87
87
|
)
|
|
88
|
+
run_group.add_argument(
|
|
89
|
+
"--chrome",
|
|
90
|
+
action="store_true",
|
|
91
|
+
help="Enable Claude in Chrome integration (passed to Claude Code)",
|
|
92
|
+
)
|
|
93
|
+
run_group.add_argument(
|
|
94
|
+
"--no-chrome",
|
|
95
|
+
action="store_true",
|
|
96
|
+
help="Disable Claude in Chrome integration (passed to Claude Code)",
|
|
97
|
+
)
|
|
88
98
|
|
|
89
99
|
# Dependency checking options
|
|
90
100
|
dep_group = parser.add_argument_group("dependency options")
|
|
@@ -76,6 +76,10 @@ def add_skill_source_subparser(subparsers) -> argparse.ArgumentParser:
|
|
|
76
76
|
dest="skip_test",
|
|
77
77
|
help="Skip immediate testing (not recommended)",
|
|
78
78
|
)
|
|
79
|
+
add_parser.add_argument(
|
|
80
|
+
"--token",
|
|
81
|
+
help="GitHub token or env var reference (e.g., ghp_xxx or $PRIVATE_TOKEN)",
|
|
82
|
+
)
|
|
79
83
|
|
|
80
84
|
# Remove repository
|
|
81
85
|
remove_parser = skill_source_subparsers.add_parser(
|
|
@@ -167,6 +167,11 @@ def add_skills_subparser(subparsers) -> argparse.ArgumentParser:
|
|
|
167
167
|
action="store_true",
|
|
168
168
|
help="Force redeployment of already deployed skills",
|
|
169
169
|
)
|
|
170
|
+
deploy_github_parser.add_argument(
|
|
171
|
+
"--all",
|
|
172
|
+
action="store_true",
|
|
173
|
+
help="Deploy all available skills, not just agent-referenced ones",
|
|
174
|
+
)
|
|
170
175
|
|
|
171
176
|
# List available GitHub skills
|
|
172
177
|
list_available_parser = skills_subparsers.add_parser(
|