mtrx-cli 0.1.11 → 0.1.13
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 +6 -2
- package/src/matrx/__init__.py +1 -1
- package/src/matrx/cli/cursor_ca.py +275 -0
- package/src/matrx/cli/cursor_config.py +262 -74
- package/src/matrx/cli/cursor_daemon.py +64 -0
- package/src/matrx/cli/cursor_proxy.py +459 -261
- package/src/matrx/cli/cursor_service.py +343 -0
- package/src/matrx/cli/launcher.py +47 -27
- package/src/matrx/cli/main.py +135 -49
package/src/matrx/cli/main.py
CHANGED
|
@@ -32,10 +32,13 @@ from matrx.cli.launcher import (
|
|
|
32
32
|
)
|
|
33
33
|
from matrx.cli.cursor_config import (
|
|
34
34
|
configure_cursor_for_proxy,
|
|
35
|
+
configure_cursor_proxy_settings,
|
|
35
36
|
cursor_is_running,
|
|
37
|
+
cursor_settings_json_path,
|
|
36
38
|
cursor_state_db_path,
|
|
37
39
|
print_manual_setup_instructions,
|
|
38
40
|
read_cursor_settings,
|
|
41
|
+
restore_cursor_proxy_settings,
|
|
39
42
|
restore_cursor_settings,
|
|
40
43
|
)
|
|
41
44
|
from matrx.cli.state import (
|
|
@@ -74,7 +77,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
74
77
|
if args.command in {"codex", "claude"}:
|
|
75
78
|
return _cmd_launch(args.command, args.route, remainder)
|
|
76
79
|
if args.command == "cursor":
|
|
77
|
-
return _cmd_cursor(args
|
|
80
|
+
return _cmd_cursor(args)
|
|
78
81
|
|
|
79
82
|
parser.print_help()
|
|
80
83
|
return 1
|
|
@@ -115,6 +118,8 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
115
118
|
|
|
116
119
|
cursor = subparsers.add_parser("cursor")
|
|
117
120
|
cursor.add_argument("--route", choices=["direct", "matrx"])
|
|
121
|
+
cursor.add_argument("--status", action="store_true", help="Check proxy status")
|
|
122
|
+
cursor.add_argument("--stop", action="store_true", help="Stop the proxy service")
|
|
118
123
|
|
|
119
124
|
return parser
|
|
120
125
|
|
|
@@ -495,19 +500,39 @@ def _cmd_use(args) -> int:
|
|
|
495
500
|
|
|
496
501
|
def _restore_cursor_if_needed() -> None:
|
|
497
502
|
import json as _json
|
|
503
|
+
|
|
504
|
+
from matrx.cli.cursor_service import is_proxy_running, uninstall_service
|
|
505
|
+
|
|
506
|
+
# Stop the MITM proxy service if it's running
|
|
507
|
+
if is_proxy_running():
|
|
508
|
+
uninstall_service()
|
|
509
|
+
print("MTRX Cursor proxy service stopped.")
|
|
510
|
+
|
|
511
|
+
# Restore settings.json (MITM proxy settings)
|
|
512
|
+
proxy_prev_path = config_dir() / "cursor-proxy-previous-settings.json"
|
|
513
|
+
if proxy_prev_path.exists():
|
|
514
|
+
try:
|
|
515
|
+
previous = _json.loads(proxy_prev_path.read_text(encoding="utf-8"))
|
|
516
|
+
if restore_cursor_proxy_settings(previous):
|
|
517
|
+
proxy_prev_path.unlink(missing_ok=True)
|
|
518
|
+
print("Cursor proxy settings restored.")
|
|
519
|
+
except Exception:
|
|
520
|
+
pass
|
|
521
|
+
|
|
522
|
+
# Restore state.vscdb (legacy Override Base URL settings)
|
|
498
523
|
prev_path = config_dir() / "cursor-previous-settings.json"
|
|
499
524
|
db_path = cursor_state_db_path()
|
|
500
|
-
if
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
525
|
+
if prev_path.exists() and db_path.exists():
|
|
526
|
+
try:
|
|
527
|
+
previous = _json.loads(prev_path.read_text(encoding="utf-8"))
|
|
528
|
+
if restore_cursor_settings(previous, db_path=db_path):
|
|
529
|
+
prev_path.unlink(missing_ok=True)
|
|
530
|
+
print("Cursor DB settings restored to previous values.")
|
|
531
|
+
else:
|
|
532
|
+
print("[warn] Could not auto-restore Cursor DB settings.")
|
|
533
|
+
except Exception:
|
|
534
|
+
pass
|
|
535
|
+
|
|
511
536
|
if cursor_is_running():
|
|
512
537
|
print(" Restart Cursor for settings to take effect.")
|
|
513
538
|
|
|
@@ -546,6 +571,11 @@ def _cmd_status() -> int:
|
|
|
546
571
|
location = config_status["config_path"] or "unknown"
|
|
547
572
|
verified_at = config_status["last_verified_at"] or "-"
|
|
548
573
|
print(f" {tool}: {status_label} ({location}, verified={verified_at})")
|
|
574
|
+
# Cursor proxy status
|
|
575
|
+
from matrx.cli.cursor_service import is_proxy_running
|
|
576
|
+
proxy_running = is_proxy_running()
|
|
577
|
+
print(f" cursor proxy: {'running' if proxy_running else 'not running'}")
|
|
578
|
+
|
|
549
579
|
print("Executables:")
|
|
550
580
|
print(f" codex: {find_executable('codex') or 'not found'}")
|
|
551
581
|
print(f" claude: {find_executable('claude') or 'not found'}")
|
|
@@ -800,32 +830,55 @@ def _cmd_launch(tool: str, route: str | None, remainder: list[str]) -> int:
|
|
|
800
830
|
return launch(plan)
|
|
801
831
|
|
|
802
832
|
|
|
803
|
-
def _cmd_cursor(
|
|
833
|
+
def _cmd_cursor(args) -> int:
|
|
834
|
+
import json as _json
|
|
835
|
+
|
|
836
|
+
from matrx.cli.cursor_ca import (
|
|
837
|
+
ca_cert_path,
|
|
838
|
+
ca_exists,
|
|
839
|
+
generate_ca,
|
|
840
|
+
is_ca_trusted,
|
|
841
|
+
trust_ca_system,
|
|
842
|
+
)
|
|
843
|
+
from matrx.cli.cursor_proxy import DEFAULT_PORT, PROXY_HOST
|
|
844
|
+
from matrx.cli.cursor_service import (
|
|
845
|
+
get_proxy_status,
|
|
846
|
+
install_service,
|
|
847
|
+
is_proxy_running,
|
|
848
|
+
uninstall_service,
|
|
849
|
+
)
|
|
850
|
+
|
|
851
|
+
route = args.route
|
|
852
|
+
|
|
853
|
+
# --status: just report proxy health
|
|
854
|
+
if args.status:
|
|
855
|
+
status = get_proxy_status()
|
|
856
|
+
if status:
|
|
857
|
+
print("MTRX Cursor proxy: running")
|
|
858
|
+
print(f" requests processed: {status.get('requests', '?')}")
|
|
859
|
+
else:
|
|
860
|
+
print("MTRX Cursor proxy: not running")
|
|
861
|
+
return 0
|
|
862
|
+
|
|
863
|
+
# --stop: tear down the proxy
|
|
864
|
+
if args.stop:
|
|
865
|
+
_restore_cursor_if_needed()
|
|
866
|
+
print("Cursor route set to direct — MTRX proxy disabled.")
|
|
867
|
+
return 0
|
|
868
|
+
|
|
804
869
|
state = load_state()
|
|
805
870
|
route, promoted = _maybe_promote_direct_route(state, "cursor", route)
|
|
806
871
|
effective_route = resolve_route(state, "cursor", route)
|
|
807
872
|
|
|
808
|
-
db_path = cursor_state_db_path()
|
|
809
|
-
|
|
810
873
|
if effective_route == "direct":
|
|
811
|
-
|
|
812
|
-
previous_json = config_dir() / "cursor-previous-settings.json"
|
|
813
|
-
if previous_json.exists():
|
|
814
|
-
import json as _json
|
|
815
|
-
try:
|
|
816
|
-
previous = _json.loads(previous_json.read_text(encoding="utf-8"))
|
|
817
|
-
if restore_cursor_settings(previous, db_path=db_path):
|
|
818
|
-
previous_json.unlink(missing_ok=True)
|
|
819
|
-
print("Cursor settings restored to previous values.")
|
|
820
|
-
else:
|
|
821
|
-
print("[warn] Could not restore Cursor settings automatically.")
|
|
822
|
-
except Exception:
|
|
823
|
-
pass
|
|
874
|
+
_restore_cursor_if_needed()
|
|
824
875
|
print("Cursor route set to direct — MTRX proxy disabled.")
|
|
825
876
|
if cursor_is_running():
|
|
826
877
|
print(" Restart Cursor for settings to take effect.")
|
|
827
878
|
return 0
|
|
828
879
|
|
|
880
|
+
# --- matrx route: set up the MITM proxy ---
|
|
881
|
+
|
|
829
882
|
try:
|
|
830
883
|
state, login_changed = _complete_matrx_login(state)
|
|
831
884
|
except ValueError as exc:
|
|
@@ -845,8 +898,9 @@ def _cmd_cursor(route: str | None) -> int:
|
|
|
845
898
|
print("No Matrx key available. Run: mtrx login matrx --key mx_...", file=sys.stderr)
|
|
846
899
|
return 1
|
|
847
900
|
|
|
848
|
-
matrx_base_url = ensure_root_url(
|
|
849
|
-
|
|
901
|
+
matrx_base_url = ensure_root_url(
|
|
902
|
+
state.get("auth", {}).get("matrx", {}).get("base_url")
|
|
903
|
+
)
|
|
850
904
|
|
|
851
905
|
if initialized or login_changed or promoted:
|
|
852
906
|
save_state(state)
|
|
@@ -856,34 +910,66 @@ def _cmd_cursor(route: str | None) -> int:
|
|
|
856
910
|
"Use `mtrx use cursor direct` to opt out.",
|
|
857
911
|
)
|
|
858
912
|
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
print(
|
|
862
|
-
|
|
913
|
+
# Step 1: Generate CA certificate if needed
|
|
914
|
+
if not ca_exists():
|
|
915
|
+
print("Generating MTRX CA certificate...")
|
|
916
|
+
generate_ca()
|
|
917
|
+
print(f" CA cert: {ca_cert_path()}")
|
|
918
|
+
|
|
919
|
+
# Step 2: Trust CA (one-time)
|
|
920
|
+
if not is_ca_trusted():
|
|
921
|
+
print("Trusting MTRX CA certificate (may require password)...")
|
|
922
|
+
if trust_ca_system():
|
|
923
|
+
print(" CA trusted in system keychain.")
|
|
924
|
+
else:
|
|
925
|
+
print(
|
|
926
|
+
f" [warn] Could not auto-trust CA. Cursor needs NODE_EXTRA_CA_CERTS={ca_cert_path()}"
|
|
927
|
+
)
|
|
928
|
+
print(
|
|
929
|
+
" You can manually trust it or set the env var before launching Cursor."
|
|
930
|
+
)
|
|
863
931
|
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
)
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
print(
|
|
870
|
-
|
|
932
|
+
# Step 3: Install and start the proxy service
|
|
933
|
+
proxy_url = f"http://{PROXY_HOST}:{DEFAULT_PORT}"
|
|
934
|
+
if is_proxy_running():
|
|
935
|
+
print(f"MTRX proxy already running on {proxy_url}")
|
|
936
|
+
else:
|
|
937
|
+
print("Starting MTRX Cursor proxy service...")
|
|
938
|
+
if install_service(
|
|
939
|
+
matrx_key=mx_key,
|
|
940
|
+
matrx_base_url=matrx_base_url,
|
|
941
|
+
host=PROXY_HOST,
|
|
942
|
+
port=DEFAULT_PORT,
|
|
943
|
+
):
|
|
944
|
+
print(f" Proxy running on {proxy_url}")
|
|
945
|
+
else:
|
|
946
|
+
print("[warn] Proxy service may not have started. Check logs at:")
|
|
947
|
+
print(f" {config_dir() / 'logs' / 'cursor-proxy.err.log'}")
|
|
871
948
|
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
prev_path.write_text(_json.dumps(previous_settings), encoding="utf-8")
|
|
949
|
+
# Step 4: Configure Cursor's settings.json
|
|
950
|
+
conf_dir = config_dir()
|
|
951
|
+
conf_dir.mkdir(parents=True, exist_ok=True)
|
|
876
952
|
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
953
|
+
previous = configure_cursor_proxy_settings(
|
|
954
|
+
proxy_url=proxy_url,
|
|
955
|
+
ca_cert_path=str(ca_cert_path()),
|
|
956
|
+
)
|
|
957
|
+
prev_path = conf_dir / "cursor-proxy-previous-settings.json"
|
|
958
|
+
prev_path.write_text(_json.dumps(previous), encoding="utf-8")
|
|
959
|
+
|
|
960
|
+
print()
|
|
961
|
+
print("Cursor configured to route ALL traffic through MTRX.")
|
|
962
|
+
print(f" proxy: {proxy_url}")
|
|
963
|
+
print(f" ca_cert: {ca_cert_path()}")
|
|
964
|
+
print(f" telemetry: {matrx_base_url}/v1/telemetry/cursor")
|
|
880
965
|
print()
|
|
881
966
|
if cursor_is_running():
|
|
882
967
|
print(" Cursor is running — restart it for settings to take effect.")
|
|
883
968
|
else:
|
|
884
969
|
print(" Settings will apply next time Cursor starts.")
|
|
885
970
|
print()
|
|
886
|
-
print("
|
|
971
|
+
print(" Check status: mtrx cursor --status")
|
|
972
|
+
print(" To disable: mtrx use cursor direct")
|
|
887
973
|
return 0
|
|
888
974
|
|
|
889
975
|
|