mtrx-cli 0.1.13 → 0.1.14
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/package.json +2 -1
- package/src/matrx/__init__.py +1 -1
- package/src/matrx/cli/cursor_launcher.py +106 -0
- package/src/matrx/cli/main.py +21 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mtrx-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
4
|
"description": "MATRX CLI for routing Codex, Claude, and Cursor through Matrx",
|
|
5
5
|
"homepage": "https://mtrx.so",
|
|
6
6
|
"repository": {
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"src/matrx/cli/cursor_ca.py",
|
|
29
29
|
"src/matrx/cli/cursor_config.py",
|
|
30
30
|
"src/matrx/cli/cursor_daemon.py",
|
|
31
|
+
"src/matrx/cli/cursor_launcher.py",
|
|
31
32
|
"src/matrx/cli/cursor_proxy.py",
|
|
32
33
|
"src/matrx/cli/cursor_service.py",
|
|
33
34
|
"src/matrx/cli/launcher.py",
|
package/src/matrx/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.1.
|
|
1
|
+
__version__ = "0.1.14"
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Cross-platform launcher for Cursor IDE with proxy environment variables.
|
|
3
|
+
|
|
4
|
+
Cursor must be started with HTTP_PROXY, HTTPS_PROXY, and NODE_EXTRA_CA_CERTS
|
|
5
|
+
for the MITM proxy to work. Launching from Dock/Spotlight does not pass
|
|
6
|
+
these env vars; this module finds the Cursor executable and launches it
|
|
7
|
+
with the correct environment on any platform.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import logging
|
|
13
|
+
import os
|
|
14
|
+
import platform
|
|
15
|
+
import shutil
|
|
16
|
+
import subprocess
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _cursor_executable_darwin() -> str | None:
|
|
23
|
+
"""macOS: /Applications/Cursor.app/Contents/MacOS/Cursor."""
|
|
24
|
+
app = Path("/Applications/Cursor.app")
|
|
25
|
+
exe = app / "Contents" / "MacOS" / "Cursor"
|
|
26
|
+
if exe.exists():
|
|
27
|
+
return str(exe)
|
|
28
|
+
return None
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _cursor_executable_linux() -> str | None:
|
|
32
|
+
"""Linux: cursor in PATH or common install locations."""
|
|
33
|
+
cursor = shutil.which("cursor")
|
|
34
|
+
if cursor:
|
|
35
|
+
return cursor
|
|
36
|
+
for path in (
|
|
37
|
+
Path.home() / ".local" / "share" / "cursor" / "bin" / "cursor",
|
|
38
|
+
Path.home() / ".local" / "bin" / "cursor",
|
|
39
|
+
):
|
|
40
|
+
if path.exists():
|
|
41
|
+
return str(path)
|
|
42
|
+
return None
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _cursor_executable_windows() -> str | None:
|
|
46
|
+
"""Windows: Cursor.exe in Local AppData."""
|
|
47
|
+
local = os.environ.get("LOCALAPPDATA", "")
|
|
48
|
+
if local:
|
|
49
|
+
for parts in (("Programs", "cursor", "Cursor.exe"), ("Cursor", "Cursor.exe")):
|
|
50
|
+
exe = Path(local) / Path(*parts)
|
|
51
|
+
if exe.exists():
|
|
52
|
+
return str(exe)
|
|
53
|
+
alt = Path(local) / "cursor" / "Cursor.exe"
|
|
54
|
+
if alt.exists():
|
|
55
|
+
return str(alt)
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def find_cursor_executable() -> str | None:
|
|
60
|
+
"""Return the path to the Cursor executable for the current platform."""
|
|
61
|
+
system = platform.system()
|
|
62
|
+
if system == "Darwin":
|
|
63
|
+
return _cursor_executable_darwin()
|
|
64
|
+
if system == "Linux":
|
|
65
|
+
return _cursor_executable_linux()
|
|
66
|
+
if system == "Windows":
|
|
67
|
+
return _cursor_executable_windows()
|
|
68
|
+
return None
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def launch_cursor_with_proxy(
|
|
72
|
+
proxy_url: str,
|
|
73
|
+
ca_cert_path: str,
|
|
74
|
+
) -> bool:
|
|
75
|
+
"""
|
|
76
|
+
Launch Cursor with HTTP_PROXY, HTTPS_PROXY, and NODE_EXTRA_CA_CERTS set.
|
|
77
|
+
|
|
78
|
+
Returns True if Cursor was launched, False if executable not found.
|
|
79
|
+
"""
|
|
80
|
+
exe = find_cursor_executable()
|
|
81
|
+
if not exe:
|
|
82
|
+
return False
|
|
83
|
+
|
|
84
|
+
env = os.environ.copy()
|
|
85
|
+
env["HTTP_PROXY"] = proxy_url
|
|
86
|
+
env["HTTPS_PROXY"] = proxy_url
|
|
87
|
+
env["NODE_EXTRA_CA_CERTS"] = str(ca_cert_path)
|
|
88
|
+
|
|
89
|
+
kwargs: dict = {}
|
|
90
|
+
if platform.system() == "Windows":
|
|
91
|
+
kwargs["creationflags"] = subprocess.CREATE_NEW_PROCESS_GROUP | subprocess.DETACHED_PROCESS
|
|
92
|
+
|
|
93
|
+
try:
|
|
94
|
+
subprocess.Popen(
|
|
95
|
+
[exe],
|
|
96
|
+
env=env,
|
|
97
|
+
stdin=subprocess.DEVNULL,
|
|
98
|
+
stdout=subprocess.DEVNULL,
|
|
99
|
+
stderr=subprocess.DEVNULL,
|
|
100
|
+
start_new_session=(platform.system() != "Windows"),
|
|
101
|
+
**kwargs,
|
|
102
|
+
)
|
|
103
|
+
return True
|
|
104
|
+
except OSError as exc:
|
|
105
|
+
logger.warning("Failed to launch Cursor: %s", exc)
|
|
106
|
+
return False
|
package/src/matrx/cli/main.py
CHANGED
|
@@ -120,6 +120,11 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
120
120
|
cursor.add_argument("--route", choices=["direct", "matrx"])
|
|
121
121
|
cursor.add_argument("--status", action="store_true", help="Check proxy status")
|
|
122
122
|
cursor.add_argument("--stop", action="store_true", help="Stop the proxy service")
|
|
123
|
+
cursor.add_argument(
|
|
124
|
+
"--launch",
|
|
125
|
+
action="store_true",
|
|
126
|
+
help="Launch Cursor with proxy env (required for traffic to flow)",
|
|
127
|
+
)
|
|
123
128
|
|
|
124
129
|
return parser
|
|
125
130
|
|
|
@@ -841,6 +846,10 @@ def _cmd_cursor(args) -> int:
|
|
|
841
846
|
trust_ca_system,
|
|
842
847
|
)
|
|
843
848
|
from matrx.cli.cursor_proxy import DEFAULT_PORT, PROXY_HOST
|
|
849
|
+
from matrx.cli.cursor_launcher import (
|
|
850
|
+
find_cursor_executable,
|
|
851
|
+
launch_cursor_with_proxy,
|
|
852
|
+
)
|
|
844
853
|
from matrx.cli.cursor_service import (
|
|
845
854
|
get_proxy_status,
|
|
846
855
|
install_service,
|
|
@@ -963,10 +972,19 @@ def _cmd_cursor(args) -> int:
|
|
|
963
972
|
print(f" ca_cert: {ca_cert_path()}")
|
|
964
973
|
print(f" telemetry: {matrx_base_url}/v1/telemetry/cursor")
|
|
965
974
|
print()
|
|
966
|
-
|
|
967
|
-
|
|
975
|
+
|
|
976
|
+
# Launch Cursor with proxy env vars (required for traffic to flow)
|
|
977
|
+
if getattr(args, "launch", False):
|
|
978
|
+
from matrx.cli.cursor_launcher import find_cursor_executable, launch_cursor_with_proxy
|
|
979
|
+
|
|
980
|
+
if launch_cursor_with_proxy(proxy_url, str(ca_cert_path())):
|
|
981
|
+
print(" Launched Cursor with proxy env vars — traffic will flow through MTRX.")
|
|
982
|
+
else:
|
|
983
|
+
print(" [warn] Could not launch Cursor. Is it installed?")
|
|
984
|
+
print(" To route traffic, launch Cursor via: mtrx cursor --launch")
|
|
968
985
|
else:
|
|
969
|
-
print("
|
|
986
|
+
print(" To route traffic, launch Cursor via: mtrx cursor --launch")
|
|
987
|
+
print(" (Cursor must be started with proxy env vars; Dock/Spotlight launch won't work)")
|
|
970
988
|
print()
|
|
971
989
|
print(" Check status: mtrx cursor --status")
|
|
972
990
|
print(" To disable: mtrx use cursor direct")
|