claude-chrome-parallel 1.0.0
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.
- package/LICENSE +21 -0
- package/README.md +501 -0
- package/assets/demo.svg +278 -0
- package/dist/cdp/client.d.ts +218 -0
- package/dist/cdp/client.d.ts.map +1 -0
- package/dist/cdp/client.js +797 -0
- package/dist/cdp/client.js.map +1 -0
- package/dist/cdp/connection-pool.d.ts +125 -0
- package/dist/cdp/connection-pool.d.ts.map +1 -0
- package/dist/cdp/connection-pool.js +443 -0
- package/dist/cdp/connection-pool.js.map +1 -0
- package/dist/cdp/screenshot-scheduler.d.ts +54 -0
- package/dist/cdp/screenshot-scheduler.d.ts.map +1 -0
- package/dist/cdp/screenshot-scheduler.js +87 -0
- package/dist/cdp/screenshot-scheduler.js.map +1 -0
- package/dist/chrome/launcher.d.ts +55 -0
- package/dist/chrome/launcher.d.ts.map +1 -0
- package/dist/chrome/launcher.js +383 -0
- package/dist/chrome/launcher.js.map +1 -0
- package/dist/chrome/pool.d.ts +54 -0
- package/dist/chrome/pool.d.ts.map +1 -0
- package/dist/chrome/pool.js +301 -0
- package/dist/chrome/pool.js.map +1 -0
- package/dist/chrome/profile-detector.d.ts +52 -0
- package/dist/chrome/profile-detector.d.ts.map +1 -0
- package/dist/chrome/profile-detector.js +246 -0
- package/dist/chrome/profile-detector.js.map +1 -0
- package/dist/cli/claude-session.d.ts +11 -0
- package/dist/cli/claude-session.js +349 -0
- package/dist/cli/claude-session.js.map +1 -0
- package/dist/cli/index.d.ts +14 -0
- package/dist/cli/index.js +858 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/install.d.ts +16 -0
- package/dist/cli/install.js +185 -0
- package/dist/cli/install.js.map +1 -0
- package/dist/cli/uninstall.d.ts +7 -0
- package/dist/cli/uninstall.js +126 -0
- package/dist/cli/uninstall.js.map +1 -0
- package/dist/cli/update-check.d.ts +9 -0
- package/dist/cli/update-check.js +141 -0
- package/dist/cli/update-check.js.map +1 -0
- package/dist/config/config-recovery.d.ts +69 -0
- package/dist/config/config-recovery.d.ts.map +1 -0
- package/dist/config/config-recovery.js +302 -0
- package/dist/config/config-recovery.js.map +1 -0
- package/dist/config/global.d.ts +49 -0
- package/dist/config/global.d.ts.map +1 -0
- package/dist/config/global.js +24 -0
- package/dist/config/global.js.map +1 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +23 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/session-isolator.d.ts +76 -0
- package/dist/config/session-isolator.d.ts.map +1 -0
- package/dist/config/session-isolator.js +268 -0
- package/dist/config/session-isolator.js.map +1 -0
- package/dist/dashboard/activity-tracker.d.ts +76 -0
- package/dist/dashboard/activity-tracker.d.ts.map +1 -0
- package/dist/dashboard/activity-tracker.js +219 -0
- package/dist/dashboard/activity-tracker.js.map +1 -0
- package/dist/dashboard/ansi.d.ts +117 -0
- package/dist/dashboard/ansi.d.ts.map +1 -0
- package/dist/dashboard/ansi.js +199 -0
- package/dist/dashboard/ansi.js.map +1 -0
- package/dist/dashboard/index.d.ts +110 -0
- package/dist/dashboard/index.d.ts.map +1 -0
- package/dist/dashboard/index.js +412 -0
- package/dist/dashboard/index.js.map +1 -0
- package/dist/dashboard/keyboard-handler.d.ts +43 -0
- package/dist/dashboard/keyboard-handler.d.ts.map +1 -0
- package/dist/dashboard/keyboard-handler.js +215 -0
- package/dist/dashboard/keyboard-handler.js.map +1 -0
- package/dist/dashboard/operation-controller.d.ts +76 -0
- package/dist/dashboard/operation-controller.d.ts.map +1 -0
- package/dist/dashboard/operation-controller.js +167 -0
- package/dist/dashboard/operation-controller.js.map +1 -0
- package/dist/dashboard/renderer.d.ts +76 -0
- package/dist/dashboard/renderer.d.ts.map +1 -0
- package/dist/dashboard/renderer.js +193 -0
- package/dist/dashboard/renderer.js.map +1 -0
- package/dist/dashboard/types.d.ts +56 -0
- package/dist/dashboard/types.d.ts.map +1 -0
- package/dist/dashboard/types.js +12 -0
- package/dist/dashboard/types.js.map +1 -0
- package/dist/dashboard/views/main-view.d.ts +23 -0
- package/dist/dashboard/views/main-view.d.ts.map +1 -0
- package/dist/dashboard/views/main-view.js +143 -0
- package/dist/dashboard/views/main-view.js.map +1 -0
- package/dist/dashboard/views/sessions-view.d.ts +22 -0
- package/dist/dashboard/views/sessions-view.d.ts.map +1 -0
- package/dist/dashboard/views/sessions-view.js +104 -0
- package/dist/dashboard/views/sessions-view.js.map +1 -0
- package/dist/dashboard/views/tabs-view.d.ts +21 -0
- package/dist/dashboard/views/tabs-view.d.ts.map +1 -0
- package/dist/dashboard/views/tabs-view.js +92 -0
- package/dist/dashboard/views/tabs-view.js.map +1 -0
- package/dist/hints/hint-engine.d.ts +77 -0
- package/dist/hints/hint-engine.d.ts.map +1 -0
- package/dist/hints/hint-engine.js +191 -0
- package/dist/hints/hint-engine.js.map +1 -0
- package/dist/hints/index.d.ts +8 -0
- package/dist/hints/index.d.ts.map +1 -0
- package/dist/hints/index.js +11 -0
- package/dist/hints/index.js.map +1 -0
- package/dist/hints/pattern-learner.d.ts +76 -0
- package/dist/hints/pattern-learner.d.ts.map +1 -0
- package/dist/hints/pattern-learner.js +254 -0
- package/dist/hints/pattern-learner.js.map +1 -0
- package/dist/hints/rules/composite-suggestions.d.ts +6 -0
- package/dist/hints/rules/composite-suggestions.d.ts.map +1 -0
- package/dist/hints/rules/composite-suggestions.js +66 -0
- package/dist/hints/rules/composite-suggestions.js.map +1 -0
- package/dist/hints/rules/error-recovery.d.ts +7 -0
- package/dist/hints/rules/error-recovery.d.ts.map +1 -0
- package/dist/hints/rules/error-recovery.js +55 -0
- package/dist/hints/rules/error-recovery.js.map +1 -0
- package/dist/hints/rules/learned-rules.d.ts +13 -0
- package/dist/hints/rules/learned-rules.d.ts.map +1 -0
- package/dist/hints/rules/learned-rules.js +27 -0
- package/dist/hints/rules/learned-rules.js.map +1 -0
- package/dist/hints/rules/repetition-detection.d.ts +7 -0
- package/dist/hints/rules/repetition-detection.d.ts.map +1 -0
- package/dist/hints/rules/repetition-detection.js +82 -0
- package/dist/hints/rules/repetition-detection.js.map +1 -0
- package/dist/hints/rules/sequence-detection.d.ts +6 -0
- package/dist/hints/rules/sequence-detection.d.ts.map +1 -0
- package/dist/hints/rules/sequence-detection.js +89 -0
- package/dist/hints/rules/sequence-detection.js.map +1 -0
- package/dist/hints/rules/success-hints.d.ts +6 -0
- package/dist/hints/rules/success-hints.d.ts.map +1 -0
- package/dist/hints/rules/success-hints.js +62 -0
- package/dist/hints/rules/success-hints.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +272 -0
- package/dist/index.js.map +1 -0
- package/dist/lightpanda/launcher.d.ts +58 -0
- package/dist/lightpanda/launcher.d.ts.map +1 -0
- package/dist/lightpanda/launcher.js +199 -0
- package/dist/lightpanda/launcher.js.map +1 -0
- package/dist/mcp-server.d.ts +129 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +641 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/memory/domain-memory.d.ts +68 -0
- package/dist/memory/domain-memory.d.ts.map +1 -0
- package/dist/memory/domain-memory.js +227 -0
- package/dist/memory/domain-memory.js.map +1 -0
- package/dist/orchestration/plan-executor.d.ts +19 -0
- package/dist/orchestration/plan-executor.d.ts.map +1 -0
- package/dist/orchestration/plan-executor.js +284 -0
- package/dist/orchestration/plan-executor.js.map +1 -0
- package/dist/orchestration/plan-registry.d.ts +55 -0
- package/dist/orchestration/plan-registry.d.ts.map +1 -0
- package/dist/orchestration/plan-registry.js +255 -0
- package/dist/orchestration/plan-registry.js.map +1 -0
- package/dist/orchestration/state-manager.d.ts +127 -0
- package/dist/orchestration/state-manager.d.ts.map +1 -0
- package/dist/orchestration/state-manager.js +438 -0
- package/dist/orchestration/state-manager.js.map +1 -0
- package/dist/orchestration/workflow-engine.d.ts +162 -0
- package/dist/orchestration/workflow-engine.d.ts.map +1 -0
- package/dist/orchestration/workflow-engine.js +731 -0
- package/dist/orchestration/workflow-engine.js.map +1 -0
- package/dist/resources/usage-guide.d.ts +13 -0
- package/dist/resources/usage-guide.d.ts.map +1 -0
- package/dist/resources/usage-guide.js +101 -0
- package/dist/resources/usage-guide.js.map +1 -0
- package/dist/router/browser-router.d.ts +51 -0
- package/dist/router/browser-router.d.ts.map +1 -0
- package/dist/router/browser-router.js +178 -0
- package/dist/router/browser-router.js.map +1 -0
- package/dist/router/cookie-sync.d.ts +48 -0
- package/dist/router/cookie-sync.d.ts.map +1 -0
- package/dist/router/cookie-sync.js +106 -0
- package/dist/router/cookie-sync.js.map +1 -0
- package/dist/router/index.d.ts +5 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +10 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/tool-routing-registry.d.ts +21 -0
- package/dist/router/tool-routing-registry.d.ts.map +1 -0
- package/dist/router/tool-routing-registry.js +90 -0
- package/dist/router/tool-routing-registry.js.map +1 -0
- package/dist/session-manager.d.ts +251 -0
- package/dist/session-manager.d.ts.map +1 -0
- package/dist/session-manager.js +912 -0
- package/dist/session-manager.js.map +1 -0
- package/dist/tools/batch-execute.d.ts +11 -0
- package/dist/tools/batch-execute.d.ts.map +1 -0
- package/dist/tools/batch-execute.js +226 -0
- package/dist/tools/batch-execute.js.map +1 -0
- package/dist/tools/click-element.d.ts +8 -0
- package/dist/tools/click-element.d.ts.map +1 -0
- package/dist/tools/click-element.js +455 -0
- package/dist/tools/click-element.js.map +1 -0
- package/dist/tools/computer.d.ts +6 -0
- package/dist/tools/computer.d.ts.map +1 -0
- package/dist/tools/computer.js +638 -0
- package/dist/tools/computer.js.map +1 -0
- package/dist/tools/console-capture.d.ts +6 -0
- package/dist/tools/console-capture.d.ts.map +1 -0
- package/dist/tools/console-capture.js +320 -0
- package/dist/tools/console-capture.js.map +1 -0
- package/dist/tools/cookies.d.ts +6 -0
- package/dist/tools/cookies.d.ts.map +1 -0
- package/dist/tools/cookies.js +263 -0
- package/dist/tools/cookies.js.map +1 -0
- package/dist/tools/drag-drop.d.ts +6 -0
- package/dist/tools/drag-drop.d.ts.map +1 -0
- package/dist/tools/drag-drop.js +252 -0
- package/dist/tools/drag-drop.js.map +1 -0
- package/dist/tools/emulate-device.d.ts +6 -0
- package/dist/tools/emulate-device.d.ts.map +1 -0
- package/dist/tools/emulate-device.js +221 -0
- package/dist/tools/emulate-device.js.map +1 -0
- package/dist/tools/file-upload.d.ts +6 -0
- package/dist/tools/file-upload.d.ts.map +1 -0
- package/dist/tools/file-upload.js +208 -0
- package/dist/tools/file-upload.js.map +1 -0
- package/dist/tools/fill-form.d.ts +8 -0
- package/dist/tools/fill-form.d.ts.map +1 -0
- package/dist/tools/fill-form.js +342 -0
- package/dist/tools/fill-form.js.map +1 -0
- package/dist/tools/find.d.ts +6 -0
- package/dist/tools/find.d.ts.map +1 -0
- package/dist/tools/find.js +330 -0
- package/dist/tools/find.js.map +1 -0
- package/dist/tools/form-input.d.ts +6 -0
- package/dist/tools/form-input.d.ts.map +1 -0
- package/dist/tools/form-input.js +181 -0
- package/dist/tools/form-input.js.map +1 -0
- package/dist/tools/geolocation.d.ts +6 -0
- package/dist/tools/geolocation.d.ts.map +1 -0
- package/dist/tools/geolocation.js +172 -0
- package/dist/tools/geolocation.js.map +1 -0
- package/dist/tools/http-auth.d.ts +6 -0
- package/dist/tools/http-auth.d.ts.map +1 -0
- package/dist/tools/http-auth.js +136 -0
- package/dist/tools/http-auth.js.map +1 -0
- package/dist/tools/index.d.ts +6 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +104 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/javascript.d.ts +6 -0
- package/dist/tools/javascript.d.ts.map +1 -0
- package/dist/tools/javascript.js +138 -0
- package/dist/tools/javascript.js.map +1 -0
- package/dist/tools/lightweight-scroll.d.ts +11 -0
- package/dist/tools/lightweight-scroll.d.ts.map +1 -0
- package/dist/tools/lightweight-scroll.js +266 -0
- package/dist/tools/lightweight-scroll.js.map +1 -0
- package/dist/tools/memory.d.ts +10 -0
- package/dist/tools/memory.d.ts.map +1 -0
- package/dist/tools/memory.js +141 -0
- package/dist/tools/memory.js.map +1 -0
- package/dist/tools/navigate.d.ts +6 -0
- package/dist/tools/navigate.d.ts.map +1 -0
- package/dist/tools/navigate.js +241 -0
- package/dist/tools/navigate.js.map +1 -0
- package/dist/tools/network.d.ts +6 -0
- package/dist/tools/network.d.ts.map +1 -0
- package/dist/tools/network.js +215 -0
- package/dist/tools/network.js.map +1 -0
- package/dist/tools/orchestration.d.ts +6 -0
- package/dist/tools/orchestration.d.ts.map +1 -0
- package/dist/tools/orchestration.js +746 -0
- package/dist/tools/orchestration.js.map +1 -0
- package/dist/tools/page-content.d.ts +6 -0
- package/dist/tools/page-content.d.ts.map +1 -0
- package/dist/tools/page-content.js +120 -0
- package/dist/tools/page-content.js.map +1 -0
- package/dist/tools/page-pdf.d.ts +6 -0
- package/dist/tools/page-pdf.d.ts.map +1 -0
- package/dist/tools/page-pdf.js +245 -0
- package/dist/tools/page-pdf.js.map +1 -0
- package/dist/tools/page-reload.d.ts +6 -0
- package/dist/tools/page-reload.d.ts.map +1 -0
- package/dist/tools/page-reload.js +89 -0
- package/dist/tools/page-reload.js.map +1 -0
- package/dist/tools/performance-metrics.d.ts +6 -0
- package/dist/tools/performance-metrics.d.ts.map +1 -0
- package/dist/tools/performance-metrics.js +158 -0
- package/dist/tools/performance-metrics.js.map +1 -0
- package/dist/tools/read-page.d.ts +6 -0
- package/dist/tools/read-page.d.ts.map +1 -0
- package/dist/tools/read-page.js +287 -0
- package/dist/tools/read-page.js.map +1 -0
- package/dist/tools/request-intercept.d.ts +6 -0
- package/dist/tools/request-intercept.d.ts.map +1 -0
- package/dist/tools/request-intercept.js +439 -0
- package/dist/tools/request-intercept.js.map +1 -0
- package/dist/tools/selector-query.d.ts +6 -0
- package/dist/tools/selector-query.d.ts.map +1 -0
- package/dist/tools/selector-query.js +206 -0
- package/dist/tools/selector-query.js.map +1 -0
- package/dist/tools/shutdown.d.ts +12 -0
- package/dist/tools/shutdown.d.ts.map +1 -0
- package/dist/tools/shutdown.js +120 -0
- package/dist/tools/shutdown.js.map +1 -0
- package/dist/tools/storage.d.ts +6 -0
- package/dist/tools/storage.d.ts.map +1 -0
- package/dist/tools/storage.js +264 -0
- package/dist/tools/storage.js.map +1 -0
- package/dist/tools/tabs-close.d.ts +6 -0
- package/dist/tools/tabs-close.d.ts.map +1 -0
- package/dist/tools/tabs-close.js +124 -0
- package/dist/tools/tabs-close.js.map +1 -0
- package/dist/tools/tabs-context.d.ts +6 -0
- package/dist/tools/tabs-context.d.ts.map +1 -0
- package/dist/tools/tabs-context.js +92 -0
- package/dist/tools/tabs-context.js.map +1 -0
- package/dist/tools/tabs-create.d.ts +6 -0
- package/dist/tools/tabs-create.d.ts.map +1 -0
- package/dist/tools/tabs-create.js +73 -0
- package/dist/tools/tabs-create.js.map +1 -0
- package/dist/tools/user-agent.d.ts +6 -0
- package/dist/tools/user-agent.d.ts.map +1 -0
- package/dist/tools/user-agent.js +128 -0
- package/dist/tools/user-agent.js.map +1 -0
- package/dist/tools/wait-and-click.d.ts +8 -0
- package/dist/tools/wait-and-click.d.ts.map +1 -0
- package/dist/tools/wait-and-click.js +290 -0
- package/dist/tools/wait-and-click.js.map +1 -0
- package/dist/tools/wait-for.d.ts +6 -0
- package/dist/tools/wait-for.d.ts.map +1 -0
- package/dist/tools/wait-for.js +248 -0
- package/dist/tools/wait-for.js.map +1 -0
- package/dist/tools/worker-create.d.ts +7 -0
- package/dist/tools/worker-create.d.ts.map +1 -0
- package/dist/tools/worker-create.js +62 -0
- package/dist/tools/worker-create.js.map +1 -0
- package/dist/tools/worker-delete.d.ts +6 -0
- package/dist/tools/worker-delete.d.ts.map +1 -0
- package/dist/tools/worker-delete.js +80 -0
- package/dist/tools/worker-delete.js.map +1 -0
- package/dist/tools/worker-list.d.ts +6 -0
- package/dist/tools/worker-list.d.ts.map +1 -0
- package/dist/tools/worker-list.js +67 -0
- package/dist/tools/worker-list.js.map +1 -0
- package/dist/tools/xpath-query.d.ts +6 -0
- package/dist/tools/xpath-query.d.ts.map +1 -0
- package/dist/tools/xpath-query.js +230 -0
- package/dist/tools/xpath-query.js.map +1 -0
- package/dist/types/browser-backend.d.ts +30 -0
- package/dist/types/browser-backend.d.ts.map +1 -0
- package/dist/types/browser-backend.js +9 -0
- package/dist/types/browser-backend.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +19 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/mcp.d.ts +54 -0
- package/dist/types/mcp.d.ts.map +1 -0
- package/dist/types/mcp.js +14 -0
- package/dist/types/mcp.js.map +1 -0
- package/dist/types/plan-cache.d.ts +121 -0
- package/dist/types/plan-cache.d.ts.map +1 -0
- package/dist/types/plan-cache.js +9 -0
- package/dist/types/plan-cache.js.map +1 -0
- package/dist/types/profile.d.ts +76 -0
- package/dist/types/profile.d.ts.map +1 -0
- package/dist/types/profile.js +35 -0
- package/dist/types/profile.js.map +1 -0
- package/dist/types/session.d.ts +65 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/session.js +6 -0
- package/dist/types/session.js.map +1 -0
- package/dist/types/tool-manifest.d.ts +52 -0
- package/dist/types/tool-manifest.d.ts.map +1 -0
- package/dist/types/tool-manifest.js +37 -0
- package/dist/types/tool-manifest.js.map +1 -0
- package/dist/utils/atomic-file.d.ts +50 -0
- package/dist/utils/atomic-file.d.ts.map +1 -0
- package/dist/utils/atomic-file.js +217 -0
- package/dist/utils/atomic-file.js.map +1 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +22 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/json-validator.d.ts +40 -0
- package/dist/utils/json-validator.d.ts.map +1 -0
- package/dist/utils/json-validator.js +295 -0
- package/dist/utils/json-validator.js.map +1 -0
- package/dist/utils/ref-id-manager.d.ts +26 -0
- package/dist/utils/ref-id-manager.d.ts.map +1 -0
- package/dist/utils/ref-id-manager.js +81 -0
- package/dist/utils/ref-id-manager.js.map +1 -0
- package/dist/utils/request-queue.d.ts +37 -0
- package/dist/utils/request-queue.d.ts.map +1 -0
- package/dist/utils/request-queue.js +110 -0
- package/dist/utils/request-queue.js.map +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1,858 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* CLI for Claude Chrome Parallel
|
|
5
|
+
*
|
|
6
|
+
* Commands:
|
|
7
|
+
* - install: Install extension and native messaging host
|
|
8
|
+
* - uninstall: Remove extension and native messaging host
|
|
9
|
+
* - serve: Start MCP server for Claude Code
|
|
10
|
+
* - sessions: List or clear sessions
|
|
11
|
+
* - launch: Start Claude Code with isolated config
|
|
12
|
+
* - doctor: Check installation status
|
|
13
|
+
* - recover: Recover corrupted .claude.json
|
|
14
|
+
*/
|
|
15
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
18
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
19
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
20
|
+
}
|
|
21
|
+
Object.defineProperty(o, k2, desc);
|
|
22
|
+
}) : (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
o[k2] = m[k];
|
|
25
|
+
}));
|
|
26
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
27
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
28
|
+
}) : function(o, v) {
|
|
29
|
+
o["default"] = v;
|
|
30
|
+
});
|
|
31
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
32
|
+
var ownKeys = function(o) {
|
|
33
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
34
|
+
var ar = [];
|
|
35
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
36
|
+
return ar;
|
|
37
|
+
};
|
|
38
|
+
return ownKeys(o);
|
|
39
|
+
};
|
|
40
|
+
return function (mod) {
|
|
41
|
+
if (mod && mod.__esModule) return mod;
|
|
42
|
+
var result = {};
|
|
43
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
44
|
+
__setModuleDefault(result, mod);
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
47
|
+
})();
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
const commander_1 = require("commander");
|
|
50
|
+
// Legacy imports - kept for backward compatibility but deprecated
|
|
51
|
+
// import { install, installNativeHost } from './install';
|
|
52
|
+
// import { uninstall } from './uninstall';
|
|
53
|
+
const path = __importStar(require("path"));
|
|
54
|
+
const fs = __importStar(require("fs"));
|
|
55
|
+
const os = __importStar(require("os"));
|
|
56
|
+
const child_process_1 = require("child_process");
|
|
57
|
+
const update_check_1 = require("./update-check");
|
|
58
|
+
const program = new commander_1.Command();
|
|
59
|
+
// Package info - from dist/cli/ go up two levels to root
|
|
60
|
+
const packageJsonPath = path.join(__dirname, '..', '..', 'package.json');
|
|
61
|
+
let version = '0.1.0';
|
|
62
|
+
try {
|
|
63
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
64
|
+
version = packageJson.version;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// Use default version
|
|
68
|
+
}
|
|
69
|
+
program
|
|
70
|
+
.name('claude-chrome-parallel')
|
|
71
|
+
.description('MCP server for parallel Claude Code browser sessions via CDP')
|
|
72
|
+
.version(version);
|
|
73
|
+
program
|
|
74
|
+
.command('install')
|
|
75
|
+
.description('[DEPRECATED] Extension install is no longer needed. Use CDP mode instead.')
|
|
76
|
+
.option('-f, --force', 'Force reinstall even if already installed')
|
|
77
|
+
.option('--extension-id <id>', 'Chrome extension ID (for native host configuration)')
|
|
78
|
+
.action(async () => {
|
|
79
|
+
console.log('⚠️ DEPRECATED: Extension installation is no longer needed.\n');
|
|
80
|
+
console.log('Claude Chrome Parallel now uses CDP (Chrome DevTools Protocol) mode,');
|
|
81
|
+
console.log('which does not require a Chrome extension.\n');
|
|
82
|
+
console.log('Quick Start:');
|
|
83
|
+
console.log(' 1. Start Chrome with debugging port:');
|
|
84
|
+
console.log(' chrome --remote-debugging-port=9222\n');
|
|
85
|
+
console.log(' 2. Add to ~/.claude.json:');
|
|
86
|
+
console.log(' {');
|
|
87
|
+
console.log(' "mcpServers": {');
|
|
88
|
+
console.log(' "chrome-parallel": {');
|
|
89
|
+
console.log(' "command": "ccp",');
|
|
90
|
+
console.log(' "args": ["serve"]');
|
|
91
|
+
console.log(' }');
|
|
92
|
+
console.log(' }');
|
|
93
|
+
console.log(' }\n');
|
|
94
|
+
console.log(' 3. Restart Claude Code\n');
|
|
95
|
+
console.log('Run "ccp doctor" to verify your setup.');
|
|
96
|
+
});
|
|
97
|
+
program
|
|
98
|
+
.command('uninstall')
|
|
99
|
+
.description('[DEPRECATED] No longer needed - CDP mode has no extension to uninstall')
|
|
100
|
+
.action(async () => {
|
|
101
|
+
console.log('⚠️ DEPRECATED: Uninstall is no longer needed.\n');
|
|
102
|
+
console.log('Claude Chrome Parallel now uses CDP mode, which has no extension to uninstall.');
|
|
103
|
+
console.log('Simply remove the MCP server config from ~/.claude.json if you want to disable it.');
|
|
104
|
+
});
|
|
105
|
+
program
|
|
106
|
+
.command('setup')
|
|
107
|
+
.description('Automatically configure MCP server for Claude Code')
|
|
108
|
+
.option('--dashboard', 'Enable terminal dashboard')
|
|
109
|
+
.option('--auto-launch', 'Auto-launch Chrome if not running (default: true)')
|
|
110
|
+
.option('-s, --scope <scope>', 'Installation scope: "user" (global, default) or "project" (current project only)', 'user')
|
|
111
|
+
.action(async (options) => {
|
|
112
|
+
const { execSync, spawnSync } = require('child_process');
|
|
113
|
+
console.log('Setting up Claude Chrome Parallel for Claude Code...\n');
|
|
114
|
+
// Check if claude CLI is available
|
|
115
|
+
try {
|
|
116
|
+
execSync('claude --version', { stdio: 'pipe' });
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
console.error('❌ Claude Code CLI not found.');
|
|
120
|
+
console.error(' Please install Claude Code first: https://claude.ai/code');
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
// Validate scope
|
|
124
|
+
const scope = options.scope || 'user';
|
|
125
|
+
if (scope !== 'user' && scope !== 'project') {
|
|
126
|
+
console.error('❌ Invalid scope. Use "user" (global) or "project" (current project only).');
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
// Build the serve arguments
|
|
130
|
+
const serveArgs = ['serve', '--auto-launch'];
|
|
131
|
+
if (options.dashboard) {
|
|
132
|
+
serveArgs.push('--dashboard');
|
|
133
|
+
}
|
|
134
|
+
// Remove existing configuration first (if any)
|
|
135
|
+
try {
|
|
136
|
+
execSync('claude mcp remove claude-chrome-parallel 2>/dev/null', { stdio: 'pipe' });
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// Ignore if not exists
|
|
140
|
+
}
|
|
141
|
+
// Use npx for auto-updates: every server start fetches the latest version
|
|
142
|
+
const fullCommand = `claude mcp add claude-chrome-parallel -s ${scope} -- npx -y claude-chrome-parallel ${serveArgs.join(' ')}`;
|
|
143
|
+
console.log(`Running: claude mcp add claude-chrome-parallel (scope: ${scope})...`);
|
|
144
|
+
try {
|
|
145
|
+
execSync(fullCommand, { stdio: 'inherit' });
|
|
146
|
+
console.log('\n✅ MCP server configured successfully!\n');
|
|
147
|
+
console.log(`Scope: ${scope === 'user' ? 'Global (all projects)' : 'Project (this directory only)'}\n`);
|
|
148
|
+
console.log('Auto-updates: enabled (via npx)\n');
|
|
149
|
+
console.log('Next steps:');
|
|
150
|
+
console.log(' 1. Restart Claude Code');
|
|
151
|
+
console.log(' 2. Just say "ccp" — that\'s it.\n');
|
|
152
|
+
console.log('Examples:');
|
|
153
|
+
console.log(' "ccp screenshot my Gmail"');
|
|
154
|
+
console.log(' "use ccp to check AWS billing"');
|
|
155
|
+
console.log(' "ccp search on naver.com"\n');
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
console.error('\n❌ Failed to configure MCP server.');
|
|
159
|
+
console.error(' You can manually add to ~/.claude.json:');
|
|
160
|
+
console.error(' {');
|
|
161
|
+
console.error(' "mcpServers": {');
|
|
162
|
+
console.error(' "claude-chrome-parallel": {');
|
|
163
|
+
console.error(' "command": "npx",');
|
|
164
|
+
console.error(` "args": ["-y", "claude-chrome-parallel", ${serveArgs.map(a => `"${a}"`).join(', ')}]`);
|
|
165
|
+
console.error(' }');
|
|
166
|
+
console.error(' }');
|
|
167
|
+
console.error(' }');
|
|
168
|
+
process.exit(1);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
program
|
|
172
|
+
.command('serve')
|
|
173
|
+
.description('Start MCP server for Claude Code')
|
|
174
|
+
.option('-p, --port <port>', 'Chrome remote debugging port', '9222')
|
|
175
|
+
.option('--auto-launch', 'Auto-launch Chrome if not running (default: false)')
|
|
176
|
+
.option('--dashboard', 'Enable terminal dashboard for real-time monitoring')
|
|
177
|
+
.option('--hybrid', 'Enable hybrid mode (Lightpanda + Chrome routing)')
|
|
178
|
+
.option('--lp-port <port>', 'Lightpanda debugging port (default: 9223)', '9223')
|
|
179
|
+
.action(async (options) => {
|
|
180
|
+
const port = parseInt(options.port, 10);
|
|
181
|
+
const autoLaunch = options.autoLaunch || false;
|
|
182
|
+
const dashboard = options.dashboard || false;
|
|
183
|
+
// Non-blocking update check (fires in background)
|
|
184
|
+
(0, update_check_1.checkForUpdates)(version).catch(() => { });
|
|
185
|
+
console.error(`[claude-chrome-parallel] Starting MCP server`);
|
|
186
|
+
console.error(`[claude-chrome-parallel] Chrome debugging port: ${port}`);
|
|
187
|
+
console.error(`[claude-chrome-parallel] Auto-launch Chrome: ${autoLaunch}`);
|
|
188
|
+
console.error(`[claude-chrome-parallel] Dashboard: ${dashboard}`);
|
|
189
|
+
// Import from built dist/ files (relative to dist/cli/)
|
|
190
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
191
|
+
const { setGlobalConfig } = require('../config/global');
|
|
192
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
193
|
+
const { getMCPServer, setMCPServerOptions } = require('../mcp-server');
|
|
194
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
195
|
+
const { registerAllTools } = require('../tools');
|
|
196
|
+
// Set global config before initializing anything
|
|
197
|
+
setGlobalConfig({ port, autoLaunch });
|
|
198
|
+
// Configure hybrid mode if enabled
|
|
199
|
+
const hybrid = options.hybrid || false;
|
|
200
|
+
const lpPort = parseInt(options.lpPort || '9223', 10);
|
|
201
|
+
if (hybrid) {
|
|
202
|
+
setGlobalConfig({
|
|
203
|
+
hybrid: {
|
|
204
|
+
enabled: true,
|
|
205
|
+
lightpandaPort: lpPort,
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
console.error(`[claude-chrome-parallel] Hybrid mode: enabled`);
|
|
209
|
+
console.error(`[claude-chrome-parallel] Lightpanda port: ${lpPort}`);
|
|
210
|
+
}
|
|
211
|
+
// Set MCP server options (including dashboard)
|
|
212
|
+
setMCPServerOptions({ dashboard });
|
|
213
|
+
const server = getMCPServer();
|
|
214
|
+
registerAllTools(server);
|
|
215
|
+
// Initialize hybrid routing if enabled
|
|
216
|
+
if (hybrid) {
|
|
217
|
+
const { getSessionManager } = require('../session-manager');
|
|
218
|
+
const sm = getSessionManager();
|
|
219
|
+
await sm.initHybrid({
|
|
220
|
+
enabled: true,
|
|
221
|
+
lightpandaPort: lpPort,
|
|
222
|
+
circuitBreaker: { maxFailures: 3, cooldownMs: 60000 },
|
|
223
|
+
cookieSync: { intervalMs: 5000 },
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
server.start();
|
|
227
|
+
});
|
|
228
|
+
program
|
|
229
|
+
.command('sessions')
|
|
230
|
+
.description('List or clear sessions')
|
|
231
|
+
.option('--clear', 'Clear all inactive sessions')
|
|
232
|
+
.action(async (options) => {
|
|
233
|
+
console.log('Session management requires the extension to be running.');
|
|
234
|
+
if (options.clear) {
|
|
235
|
+
console.log('To clear sessions, use the extension popup.');
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
console.log('To view sessions, check the extension popup in Chrome.');
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
program
|
|
242
|
+
.command('doctor')
|
|
243
|
+
.description('Check installation status')
|
|
244
|
+
.action(async () => {
|
|
245
|
+
console.log('Checking installation status...\n');
|
|
246
|
+
// Core checks (required for CDP mode)
|
|
247
|
+
const coreChecks = {
|
|
248
|
+
'Node.js version (>=18)': checkNodeVersion(),
|
|
249
|
+
'.claude.json health': await checkClaudeConfigHealth(),
|
|
250
|
+
'Chrome debugging port': await checkChromeDebugPort(),
|
|
251
|
+
};
|
|
252
|
+
console.log('Core Requirements:');
|
|
253
|
+
for (const [name, passed] of Object.entries(coreChecks)) {
|
|
254
|
+
const status = passed ? '✅' : '❌';
|
|
255
|
+
console.log(` ${status} ${name}`);
|
|
256
|
+
}
|
|
257
|
+
const allPassed = Object.values(coreChecks).every(Boolean);
|
|
258
|
+
console.log();
|
|
259
|
+
if (allPassed) {
|
|
260
|
+
console.log('All checks passed! Ready to use with Claude Code.');
|
|
261
|
+
console.log('\nUsage:');
|
|
262
|
+
console.log(' 1. Start Chrome with: chrome --remote-debugging-port=9222');
|
|
263
|
+
console.log(' 2. Add to ~/.claude.json:');
|
|
264
|
+
console.log(' "mcpServers": { "chrome-parallel": { "command": "ccp", "args": ["serve"] } }');
|
|
265
|
+
console.log(' 3. Restart Claude Code');
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
if (!coreChecks['Chrome debugging port']) {
|
|
269
|
+
console.log('Chrome is not running with debugging port.');
|
|
270
|
+
console.log('Start Chrome with: chrome --remote-debugging-port=9222');
|
|
271
|
+
}
|
|
272
|
+
if (!coreChecks['.claude.json health']) {
|
|
273
|
+
console.log('Run "claude-chrome-parallel recover" to fix .claude.json');
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
program
|
|
278
|
+
.command('launch')
|
|
279
|
+
.description('Start Claude Code with isolated config (prevents corruption)')
|
|
280
|
+
.option('--sync-back', 'Sync config changes back to original after session')
|
|
281
|
+
.option('--keep-session', 'Keep session directory after exit (for debugging)')
|
|
282
|
+
.argument('[args...]', 'Arguments to pass to claude')
|
|
283
|
+
.action(async (args, options) => {
|
|
284
|
+
const sessionId = generateSessionId();
|
|
285
|
+
const sessionDir = path.join(getSessionsDir(), sessionId);
|
|
286
|
+
console.log(`Creating isolated session: ${sessionId}`);
|
|
287
|
+
// Create session directory
|
|
288
|
+
fs.mkdirSync(sessionDir, { recursive: true });
|
|
289
|
+
// Copy existing .claude.json if it exists
|
|
290
|
+
const originalConfig = path.join(os.homedir(), '.claude.json');
|
|
291
|
+
const sessionConfig = path.join(sessionDir, '.claude.json');
|
|
292
|
+
if (fs.existsSync(originalConfig)) {
|
|
293
|
+
// Validate before copying
|
|
294
|
+
const content = fs.readFileSync(originalConfig, 'utf8');
|
|
295
|
+
if (isValidJson(content)) {
|
|
296
|
+
fs.copyFileSync(originalConfig, sessionConfig);
|
|
297
|
+
console.log('Copied existing config to session');
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
console.warn('Warning: Original .claude.json is corrupted, starting fresh');
|
|
301
|
+
fs.writeFileSync(sessionConfig, '{}');
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
fs.writeFileSync(sessionConfig, '{}');
|
|
306
|
+
}
|
|
307
|
+
// Create session metadata
|
|
308
|
+
const metadata = {
|
|
309
|
+
id: sessionId,
|
|
310
|
+
createdAt: new Date().toISOString(),
|
|
311
|
+
originalHome: os.homedir(),
|
|
312
|
+
};
|
|
313
|
+
fs.writeFileSync(path.join(sessionDir, '.session-metadata.json'), JSON.stringify(metadata, null, 2));
|
|
314
|
+
console.log('Starting Claude Code with isolated config...\n');
|
|
315
|
+
// Set up environment with isolated HOME
|
|
316
|
+
const env = {
|
|
317
|
+
...process.env,
|
|
318
|
+
HOME: sessionDir,
|
|
319
|
+
USERPROFILE: sessionDir,
|
|
320
|
+
CLAUDE_CONFIG_DIR: sessionDir,
|
|
321
|
+
};
|
|
322
|
+
// Find claude command
|
|
323
|
+
const claudeCmd = process.platform === 'win32' ? 'claude.cmd' : 'claude';
|
|
324
|
+
// Spawn claude with isolated environment
|
|
325
|
+
const child = (0, child_process_1.spawn)(claudeCmd, args, {
|
|
326
|
+
env,
|
|
327
|
+
stdio: 'inherit',
|
|
328
|
+
shell: true,
|
|
329
|
+
});
|
|
330
|
+
// Handle exit
|
|
331
|
+
child.on('close', async (code) => {
|
|
332
|
+
console.log(`\nClaude Code exited with code ${code}`);
|
|
333
|
+
// Sync back if requested
|
|
334
|
+
if (options.syncBack && fs.existsSync(sessionConfig)) {
|
|
335
|
+
console.log('Syncing config back to original location...');
|
|
336
|
+
const sessionContent = fs.readFileSync(sessionConfig, 'utf8');
|
|
337
|
+
if (isValidJson(sessionContent)) {
|
|
338
|
+
// Backup original first
|
|
339
|
+
if (fs.existsSync(originalConfig)) {
|
|
340
|
+
await createBackupFile(originalConfig);
|
|
341
|
+
}
|
|
342
|
+
fs.writeFileSync(originalConfig, sessionContent);
|
|
343
|
+
console.log('Config synced successfully');
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
console.error('Session config is corrupted, not syncing back');
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
// Cleanup session
|
|
350
|
+
if (!options.keepSession) {
|
|
351
|
+
console.log('Cleaning up session directory...');
|
|
352
|
+
fs.rmSync(sessionDir, { recursive: true, force: true });
|
|
353
|
+
console.log('Session cleaned up');
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
console.log(`Session kept at: ${sessionDir}`);
|
|
357
|
+
}
|
|
358
|
+
process.exit(code ?? 0);
|
|
359
|
+
});
|
|
360
|
+
// Forward signals
|
|
361
|
+
process.on('SIGINT', () => child.kill('SIGINT'));
|
|
362
|
+
process.on('SIGTERM', () => child.kill('SIGTERM'));
|
|
363
|
+
});
|
|
364
|
+
program
|
|
365
|
+
.command('recover')
|
|
366
|
+
.description('Recover corrupted .claude.json')
|
|
367
|
+
.option('--backup <name>', 'Restore from specific backup')
|
|
368
|
+
.option('--list-backups', 'List available backups')
|
|
369
|
+
.option('--force-new', 'Create new empty config (loses all data)')
|
|
370
|
+
.action(async (options) => {
|
|
371
|
+
const configPath = path.join(os.homedir(), '.claude.json');
|
|
372
|
+
const backupDir = path.join(os.homedir(), '.claude-chrome-parallel', 'backups');
|
|
373
|
+
// List backups
|
|
374
|
+
if (options.listBackups) {
|
|
375
|
+
console.log('Available backups:\n');
|
|
376
|
+
if (!fs.existsSync(backupDir)) {
|
|
377
|
+
console.log('No backups found');
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
const backups = fs.readdirSync(backupDir)
|
|
381
|
+
.filter(f => f.startsWith('.claude.json.'))
|
|
382
|
+
.sort()
|
|
383
|
+
.reverse();
|
|
384
|
+
if (backups.length === 0) {
|
|
385
|
+
console.log('No backups found');
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
for (const backup of backups) {
|
|
389
|
+
const stats = fs.statSync(path.join(backupDir, backup));
|
|
390
|
+
console.log(` ${backup} (${formatBytes(stats.size)})`);
|
|
391
|
+
}
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
// Force new config
|
|
395
|
+
if (options.forceNew) {
|
|
396
|
+
if (fs.existsSync(configPath)) {
|
|
397
|
+
await createBackupFile(configPath);
|
|
398
|
+
}
|
|
399
|
+
fs.writeFileSync(configPath, '{}');
|
|
400
|
+
console.log('Created new empty .claude.json');
|
|
401
|
+
console.log('Warning: All previous settings have been lost (backup created)');
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
// Restore from specific backup
|
|
405
|
+
if (options.backup) {
|
|
406
|
+
const backupPath = path.join(backupDir, options.backup);
|
|
407
|
+
if (!fs.existsSync(backupPath)) {
|
|
408
|
+
console.error(`Backup not found: ${options.backup}`);
|
|
409
|
+
process.exit(1);
|
|
410
|
+
}
|
|
411
|
+
const content = fs.readFileSync(backupPath, 'utf8');
|
|
412
|
+
if (!isValidJson(content)) {
|
|
413
|
+
console.error('Selected backup is also corrupted');
|
|
414
|
+
process.exit(1);
|
|
415
|
+
}
|
|
416
|
+
if (fs.existsSync(configPath)) {
|
|
417
|
+
await createBackupFile(configPath);
|
|
418
|
+
}
|
|
419
|
+
fs.writeFileSync(configPath, content);
|
|
420
|
+
console.log(`Restored from backup: ${options.backup}`);
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
// Auto-recover
|
|
424
|
+
console.log('Checking .claude.json...\n');
|
|
425
|
+
if (!fs.existsSync(configPath)) {
|
|
426
|
+
console.log('No .claude.json found - nothing to recover');
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
430
|
+
if (isValidJson(content)) {
|
|
431
|
+
console.log('✅ .claude.json is valid - no recovery needed');
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
console.log('❌ .claude.json is corrupted');
|
|
435
|
+
console.log('Attempting recovery...\n');
|
|
436
|
+
// Create backup
|
|
437
|
+
const backup = await createBackupFile(configPath);
|
|
438
|
+
console.log(`Backup created: ${backup}`);
|
|
439
|
+
// Try to extract valid JSON
|
|
440
|
+
const recovered = attemptJsonRecovery(content);
|
|
441
|
+
if (recovered) {
|
|
442
|
+
fs.writeFileSync(configPath, JSON.stringify(recovered, null, 2));
|
|
443
|
+
console.log('✅ Successfully recovered .claude.json');
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
// Try to restore from backup
|
|
447
|
+
if (fs.existsSync(backupDir)) {
|
|
448
|
+
const backups = fs.readdirSync(backupDir)
|
|
449
|
+
.filter(f => f.startsWith('.claude.json.'))
|
|
450
|
+
.sort()
|
|
451
|
+
.reverse();
|
|
452
|
+
for (const backupFile of backups) {
|
|
453
|
+
const backupContent = fs.readFileSync(path.join(backupDir, backupFile), 'utf8');
|
|
454
|
+
if (isValidJson(backupContent)) {
|
|
455
|
+
fs.writeFileSync(configPath, backupContent);
|
|
456
|
+
console.log(`✅ Restored from backup: ${backupFile}`);
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
// Last resort: create empty config
|
|
462
|
+
fs.writeFileSync(configPath, '{}');
|
|
463
|
+
console.log('⚠️ Could not recover - created new empty config');
|
|
464
|
+
console.log('Your corrupted file has been backed up');
|
|
465
|
+
});
|
|
466
|
+
program
|
|
467
|
+
.command('status')
|
|
468
|
+
.description('Show session manager status and statistics')
|
|
469
|
+
.option('--json', 'Output as JSON')
|
|
470
|
+
.action(async (options) => {
|
|
471
|
+
const sessionsDir = getSessionsDir();
|
|
472
|
+
const backupDir = path.join(os.homedir(), '.claude-chrome-parallel', 'backups');
|
|
473
|
+
const configPath = path.join(os.homedir(), '.claude.json');
|
|
474
|
+
// Gather statistics
|
|
475
|
+
let activeSessions = 0;
|
|
476
|
+
let totalSessionsSize = 0;
|
|
477
|
+
const sessionDetails = [];
|
|
478
|
+
if (fs.existsSync(sessionsDir)) {
|
|
479
|
+
const entries = fs.readdirSync(sessionsDir, { withFileTypes: true });
|
|
480
|
+
const now = Date.now();
|
|
481
|
+
for (const entry of entries) {
|
|
482
|
+
if (!entry.isDirectory())
|
|
483
|
+
continue;
|
|
484
|
+
const sessionDir = path.join(sessionsDir, entry.name);
|
|
485
|
+
const metadataPath = path.join(sessionDir, '.session-metadata.json');
|
|
486
|
+
activeSessions++;
|
|
487
|
+
const size = getDirSize(sessionDir);
|
|
488
|
+
totalSessionsSize += size;
|
|
489
|
+
let age = 'unknown';
|
|
490
|
+
if (fs.existsSync(metadataPath)) {
|
|
491
|
+
try {
|
|
492
|
+
const metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
|
|
493
|
+
const createdAt = new Date(metadata.createdAt).getTime();
|
|
494
|
+
age = formatDuration(now - createdAt);
|
|
495
|
+
}
|
|
496
|
+
catch {
|
|
497
|
+
// ignore
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
sessionDetails.push({
|
|
501
|
+
id: entry.name,
|
|
502
|
+
age,
|
|
503
|
+
size: formatBytes(size),
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
// Count backups
|
|
508
|
+
let backupCount = 0;
|
|
509
|
+
let backupSize = 0;
|
|
510
|
+
if (fs.existsSync(backupDir)) {
|
|
511
|
+
const backups = fs.readdirSync(backupDir).filter(f => f.startsWith('.claude.json.'));
|
|
512
|
+
backupCount = backups.length;
|
|
513
|
+
for (const backup of backups) {
|
|
514
|
+
const stats = fs.statSync(path.join(backupDir, backup));
|
|
515
|
+
backupSize += stats.size;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
// Check config health
|
|
519
|
+
let configHealthy = true;
|
|
520
|
+
let configError = '';
|
|
521
|
+
if (fs.existsSync(configPath)) {
|
|
522
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
523
|
+
if (!isValidJson(content)) {
|
|
524
|
+
configHealthy = false;
|
|
525
|
+
configError = 'Invalid JSON (corrupted)';
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
// Memory usage
|
|
529
|
+
const memUsage = process.memoryUsage();
|
|
530
|
+
const status = {
|
|
531
|
+
sessions: {
|
|
532
|
+
active: activeSessions,
|
|
533
|
+
totalSize: formatBytes(totalSessionsSize),
|
|
534
|
+
details: sessionDetails,
|
|
535
|
+
},
|
|
536
|
+
backups: {
|
|
537
|
+
count: backupCount,
|
|
538
|
+
totalSize: formatBytes(backupSize),
|
|
539
|
+
},
|
|
540
|
+
config: {
|
|
541
|
+
healthy: configHealthy,
|
|
542
|
+
error: configError || undefined,
|
|
543
|
+
},
|
|
544
|
+
memory: {
|
|
545
|
+
heapUsed: formatBytes(memUsage.heapUsed),
|
|
546
|
+
heapTotal: formatBytes(memUsage.heapTotal),
|
|
547
|
+
rss: formatBytes(memUsage.rss),
|
|
548
|
+
},
|
|
549
|
+
};
|
|
550
|
+
if (options.json) {
|
|
551
|
+
console.log(JSON.stringify(status, null, 2));
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
// Pretty print
|
|
555
|
+
console.log('Claude Chrome Parallel Status');
|
|
556
|
+
console.log('═'.repeat(40));
|
|
557
|
+
console.log();
|
|
558
|
+
// Sessions
|
|
559
|
+
console.log('Sessions');
|
|
560
|
+
console.log('─'.repeat(20));
|
|
561
|
+
console.log(` Active: ${activeSessions}`);
|
|
562
|
+
console.log(` Total Size: ${formatBytes(totalSessionsSize)}`);
|
|
563
|
+
if (sessionDetails.length > 0) {
|
|
564
|
+
console.log(' Details:');
|
|
565
|
+
for (const s of sessionDetails) {
|
|
566
|
+
console.log(` - ${s.id} (${s.age}, ${s.size})`);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
console.log();
|
|
570
|
+
// Backups
|
|
571
|
+
console.log('Backups');
|
|
572
|
+
console.log('─'.repeat(20));
|
|
573
|
+
console.log(` Count: ${backupCount}`);
|
|
574
|
+
console.log(` Total Size: ${formatBytes(backupSize)}`);
|
|
575
|
+
console.log();
|
|
576
|
+
// Config
|
|
577
|
+
console.log('Config Health');
|
|
578
|
+
console.log('─'.repeat(20));
|
|
579
|
+
if (configHealthy) {
|
|
580
|
+
console.log(' ✅ .claude.json is healthy');
|
|
581
|
+
}
|
|
582
|
+
else {
|
|
583
|
+
console.log(` ❌ .claude.json: ${configError}`);
|
|
584
|
+
console.log(' Run: claude-chrome-parallel recover');
|
|
585
|
+
}
|
|
586
|
+
console.log();
|
|
587
|
+
// Memory
|
|
588
|
+
console.log('Memory');
|
|
589
|
+
console.log('─'.repeat(20));
|
|
590
|
+
console.log(` Heap Used: ${formatBytes(memUsage.heapUsed)}`);
|
|
591
|
+
console.log(` Heap Total: ${formatBytes(memUsage.heapTotal)}`);
|
|
592
|
+
console.log(` RSS: ${formatBytes(memUsage.rss)}`);
|
|
593
|
+
});
|
|
594
|
+
program
|
|
595
|
+
.command('cleanup')
|
|
596
|
+
.description('Clean up stale sessions and old backups')
|
|
597
|
+
.option('--max-age <hours>', 'Max session age in hours (default: 24)', '24')
|
|
598
|
+
.option('--keep-backups <count>', 'Number of backups to keep (default: 10)', '10')
|
|
599
|
+
.action((options) => {
|
|
600
|
+
const maxAgeMs = parseInt(options.maxAge, 10) * 60 * 60 * 1000;
|
|
601
|
+
const keepBackups = parseInt(options.keepBackups, 10);
|
|
602
|
+
console.log('Cleaning up stale sessions...\n');
|
|
603
|
+
// Clean up sessions
|
|
604
|
+
const sessionsDir = getSessionsDir();
|
|
605
|
+
let sessionsRemoved = 0;
|
|
606
|
+
if (fs.existsSync(sessionsDir)) {
|
|
607
|
+
const entries = fs.readdirSync(sessionsDir, { withFileTypes: true });
|
|
608
|
+
const now = Date.now();
|
|
609
|
+
for (const entry of entries) {
|
|
610
|
+
if (!entry.isDirectory())
|
|
611
|
+
continue;
|
|
612
|
+
const sessionDir = path.join(sessionsDir, entry.name);
|
|
613
|
+
const metadataPath = path.join(sessionDir, '.session-metadata.json');
|
|
614
|
+
let shouldDelete = false;
|
|
615
|
+
if (fs.existsSync(metadataPath)) {
|
|
616
|
+
try {
|
|
617
|
+
const metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
|
|
618
|
+
const createdAt = new Date(metadata.createdAt).getTime();
|
|
619
|
+
shouldDelete = (now - createdAt) > maxAgeMs;
|
|
620
|
+
}
|
|
621
|
+
catch {
|
|
622
|
+
shouldDelete = true; // Invalid metadata
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
else {
|
|
626
|
+
shouldDelete = true; // No metadata
|
|
627
|
+
}
|
|
628
|
+
if (shouldDelete) {
|
|
629
|
+
fs.rmSync(sessionDir, { recursive: true, force: true });
|
|
630
|
+
sessionsRemoved++;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
console.log(`Removed ${sessionsRemoved} stale session(s)`);
|
|
635
|
+
// Clean up backups
|
|
636
|
+
const backupDir = path.join(os.homedir(), '.claude-chrome-parallel', 'backups');
|
|
637
|
+
let backupsRemoved = 0;
|
|
638
|
+
if (fs.existsSync(backupDir)) {
|
|
639
|
+
const backups = fs.readdirSync(backupDir)
|
|
640
|
+
.filter(f => f.startsWith('.claude.json.'))
|
|
641
|
+
.sort()
|
|
642
|
+
.reverse();
|
|
643
|
+
const toRemove = backups.slice(keepBackups);
|
|
644
|
+
for (const backup of toRemove) {
|
|
645
|
+
fs.unlinkSync(path.join(backupDir, backup));
|
|
646
|
+
backupsRemoved++;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
console.log(`Removed ${backupsRemoved} old backup(s)`);
|
|
650
|
+
console.log('\nCleanup complete!');
|
|
651
|
+
});
|
|
652
|
+
/**
|
|
653
|
+
* Get the extension installation path
|
|
654
|
+
*/
|
|
655
|
+
function getExtensionPath() {
|
|
656
|
+
return path.join(os.homedir(), '.claude-chrome-parallel', 'extension');
|
|
657
|
+
}
|
|
658
|
+
/**
|
|
659
|
+
* Check if native host manifest exists
|
|
660
|
+
*/
|
|
661
|
+
function checkNativeHostManifest() {
|
|
662
|
+
const platform = os.platform();
|
|
663
|
+
let manifestPath;
|
|
664
|
+
switch (platform) {
|
|
665
|
+
case 'win32':
|
|
666
|
+
// Check registry or user data path
|
|
667
|
+
manifestPath = path.join(os.homedir(), 'AppData', 'Local', 'Google', 'Chrome', 'User Data', 'NativeMessagingHosts', 'com.anthropic.claude_chrome_parallel.json');
|
|
668
|
+
break;
|
|
669
|
+
case 'darwin':
|
|
670
|
+
manifestPath = path.join(os.homedir(), 'Library', 'Application Support', 'Google', 'Chrome', 'NativeMessagingHosts', 'com.anthropic.claude_chrome_parallel.json');
|
|
671
|
+
break;
|
|
672
|
+
default:
|
|
673
|
+
manifestPath = path.join(os.homedir(), '.config', 'google-chrome', 'NativeMessagingHosts', 'com.anthropic.claude_chrome_parallel.json');
|
|
674
|
+
}
|
|
675
|
+
return fs.existsSync(manifestPath);
|
|
676
|
+
}
|
|
677
|
+
/**
|
|
678
|
+
* Check Node.js version
|
|
679
|
+
*/
|
|
680
|
+
function checkNodeVersion() {
|
|
681
|
+
const version = process.version;
|
|
682
|
+
const major = parseInt(version.slice(1).split('.')[0], 10);
|
|
683
|
+
return major >= 18;
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* Check if Chrome is running with debugging port
|
|
687
|
+
*/
|
|
688
|
+
async function checkChromeDebugPort(port = 9222) {
|
|
689
|
+
try {
|
|
690
|
+
const http = await Promise.resolve().then(() => __importStar(require('http')));
|
|
691
|
+
return new Promise((resolve) => {
|
|
692
|
+
const req = http.get(`http://localhost:${port}/json/version`, (res) => {
|
|
693
|
+
resolve(res.statusCode === 200);
|
|
694
|
+
});
|
|
695
|
+
req.on('error', () => resolve(false));
|
|
696
|
+
req.setTimeout(2000, () => {
|
|
697
|
+
req.destroy();
|
|
698
|
+
resolve(false);
|
|
699
|
+
});
|
|
700
|
+
});
|
|
701
|
+
}
|
|
702
|
+
catch {
|
|
703
|
+
return false;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* Check .claude.json health
|
|
708
|
+
*/
|
|
709
|
+
async function checkClaudeConfigHealth() {
|
|
710
|
+
const configPath = path.join(os.homedir(), '.claude.json');
|
|
711
|
+
if (!fs.existsSync(configPath)) {
|
|
712
|
+
return true; // No config is fine
|
|
713
|
+
}
|
|
714
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
715
|
+
return isValidJson(content);
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Get sessions directory
|
|
719
|
+
*/
|
|
720
|
+
function getSessionsDir() {
|
|
721
|
+
return path.join(os.homedir(), '.claude-chrome-parallel', 'sessions');
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* Generate a unique session ID
|
|
725
|
+
*/
|
|
726
|
+
function generateSessionId() {
|
|
727
|
+
const timestamp = Date.now().toString(36);
|
|
728
|
+
const random = Math.random().toString(36).substring(2, 8);
|
|
729
|
+
return `${timestamp}-${random}`;
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* Check if string is valid JSON
|
|
733
|
+
*/
|
|
734
|
+
function isValidJson(content) {
|
|
735
|
+
try {
|
|
736
|
+
JSON.parse(content);
|
|
737
|
+
return true;
|
|
738
|
+
}
|
|
739
|
+
catch {
|
|
740
|
+
return false;
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* Create a backup of a file
|
|
745
|
+
*/
|
|
746
|
+
async function createBackupFile(filePath) {
|
|
747
|
+
const backupDir = path.join(os.homedir(), '.claude-chrome-parallel', 'backups');
|
|
748
|
+
fs.mkdirSync(backupDir, { recursive: true });
|
|
749
|
+
const basename = path.basename(filePath);
|
|
750
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
751
|
+
const backupName = `${basename}.${timestamp}.bak`;
|
|
752
|
+
const backupPath = path.join(backupDir, backupName);
|
|
753
|
+
fs.copyFileSync(filePath, backupPath);
|
|
754
|
+
return backupPath;
|
|
755
|
+
}
|
|
756
|
+
/**
|
|
757
|
+
* Format bytes as human readable string
|
|
758
|
+
*/
|
|
759
|
+
function formatBytes(bytes) {
|
|
760
|
+
if (bytes === 0)
|
|
761
|
+
return '0 B';
|
|
762
|
+
const k = 1024;
|
|
763
|
+
const sizes = ['B', 'KB', 'MB', 'GB'];
|
|
764
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
765
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Format duration in milliseconds as human readable string
|
|
769
|
+
*/
|
|
770
|
+
function formatDuration(ms) {
|
|
771
|
+
const seconds = Math.floor(ms / 1000);
|
|
772
|
+
const minutes = Math.floor(seconds / 60);
|
|
773
|
+
const hours = Math.floor(minutes / 60);
|
|
774
|
+
const days = Math.floor(hours / 24);
|
|
775
|
+
if (days > 0)
|
|
776
|
+
return `${days}d ${hours % 24}h`;
|
|
777
|
+
if (hours > 0)
|
|
778
|
+
return `${hours}h ${minutes % 60}m`;
|
|
779
|
+
if (minutes > 0)
|
|
780
|
+
return `${minutes}m ${seconds % 60}s`;
|
|
781
|
+
return `${seconds}s`;
|
|
782
|
+
}
|
|
783
|
+
/**
|
|
784
|
+
* Get total size of a directory recursively
|
|
785
|
+
*/
|
|
786
|
+
function getDirSize(dirPath) {
|
|
787
|
+
let totalSize = 0;
|
|
788
|
+
try {
|
|
789
|
+
const entries = fs.readdirSync(dirPath, { withFileTypes: true });
|
|
790
|
+
for (const entry of entries) {
|
|
791
|
+
const fullPath = path.join(dirPath, entry.name);
|
|
792
|
+
if (entry.isDirectory()) {
|
|
793
|
+
totalSize += getDirSize(fullPath);
|
|
794
|
+
}
|
|
795
|
+
else if (entry.isFile()) {
|
|
796
|
+
totalSize += fs.statSync(fullPath).size;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
catch {
|
|
801
|
+
// Permission denied or other errors
|
|
802
|
+
}
|
|
803
|
+
return totalSize;
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* Attempt to recover valid JSON from corrupted content
|
|
807
|
+
*/
|
|
808
|
+
function attemptJsonRecovery(content) {
|
|
809
|
+
const trimmed = content.trim();
|
|
810
|
+
// Try to extract first valid JSON object from concatenated content
|
|
811
|
+
if (trimmed.includes('}{')) {
|
|
812
|
+
// Find matching brace for first object
|
|
813
|
+
let depth = 0;
|
|
814
|
+
let inString = false;
|
|
815
|
+
let escapeNext = false;
|
|
816
|
+
for (let i = 0; i < trimmed.length; i++) {
|
|
817
|
+
const char = trimmed[i];
|
|
818
|
+
if (escapeNext) {
|
|
819
|
+
escapeNext = false;
|
|
820
|
+
continue;
|
|
821
|
+
}
|
|
822
|
+
if (char === '\\' && inString) {
|
|
823
|
+
escapeNext = true;
|
|
824
|
+
continue;
|
|
825
|
+
}
|
|
826
|
+
if (char === '"') {
|
|
827
|
+
inString = !inString;
|
|
828
|
+
continue;
|
|
829
|
+
}
|
|
830
|
+
if (inString)
|
|
831
|
+
continue;
|
|
832
|
+
if (char === '{')
|
|
833
|
+
depth++;
|
|
834
|
+
else if (char === '}') {
|
|
835
|
+
depth--;
|
|
836
|
+
if (depth === 0) {
|
|
837
|
+
const firstObject = trimmed.substring(0, i + 1);
|
|
838
|
+
try {
|
|
839
|
+
return JSON.parse(firstObject);
|
|
840
|
+
}
|
|
841
|
+
catch {
|
|
842
|
+
// Try second object
|
|
843
|
+
const secondObject = trimmed.substring(i + 1);
|
|
844
|
+
try {
|
|
845
|
+
return JSON.parse(secondObject);
|
|
846
|
+
}
|
|
847
|
+
catch {
|
|
848
|
+
break;
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
return null;
|
|
856
|
+
}
|
|
857
|
+
program.parse();
|
|
858
|
+
//# sourceMappingURL=index.js.map
|