mtrx-cli 0.1.20 → 0.1.21

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mtrx-cli",
3
- "version": "0.1.20",
3
+ "version": "0.1.21",
4
4
  "description": "MATRX CLI for routing Codex, Claude, and Cursor through Matrx",
5
5
  "homepage": "https://mtrx.so",
6
6
  "repository": {
@@ -1 +1 @@
1
- __version__ = "0.1.19"
1
+ __version__ = "0.1.21"
@@ -537,6 +537,11 @@ def _build_codex_env(
537
537
  header_parts.append(f'"X-Matrx-Group" = "{group_id}"')
538
538
  if project_id:
539
539
  header_parts.append(f'"X-Matrx-Project-Id" = "{project_id}"')
540
+ _git_branch, _git_commit = _capture_git_context(_workspace_cwd(env))
541
+ if _git_branch:
542
+ header_parts.append(f'"X-Matrx-Branch" = "{_git_branch}"')
543
+ if _git_commit:
544
+ header_parts.append(f'"X-Matrx-Commit" = "{_git_commit}"')
540
545
  if env_b64:
541
546
  header_parts.append(f'"X-Matrx-Env" = "{env_b64}"')
542
547
  headers_str = ", ".join(header_parts)
@@ -680,6 +685,11 @@ def _build_claude_env(
680
685
  custom_headers += f"\nx-matrx-group: {group_id}"
681
686
  if project_id:
682
687
  custom_headers += f"\nx-matrx-project-id: {project_id}"
688
+ _git_branch, _git_commit = _capture_git_context(_workspace_cwd(env))
689
+ if _git_branch:
690
+ custom_headers += f"\nx-matrx-branch: {_git_branch}"
691
+ if _git_commit:
692
+ custom_headers += f"\nx-matrx-commit: {_git_commit}"
683
693
  if env_b64:
684
694
  custom_headers += f"\nx-matrx-env: {env_b64}"
685
695
  env["ANTHROPIC_CUSTOM_HEADERS"] = custom_headers
@@ -466,10 +466,13 @@ def _cmd_login(args) -> int:
466
466
 
467
467
  key = (args.key or "").strip()
468
468
  if provider == "matrx":
469
+ url_changed = False
469
470
  if args.base_url:
470
471
  state["auth"]["matrx"]["base_url"] = args.base_url.strip()
472
+ url_changed = True
471
473
  if args.app_url:
472
474
  state["auth"]["matrx"]["app_url"] = args.app_url.strip()
475
+ url_changed = True
473
476
  elif not state["auth"]["matrx"].get("app_url"):
474
477
  state["auth"]["matrx"]["app_url"] = ensure_app_url(
475
478
  None,
@@ -484,13 +487,14 @@ def _cmd_login(args) -> int:
484
487
  except ValueError as exc:
485
488
  print(str(exc), file=sys.stderr)
486
489
  return 1
487
- if changed:
490
+ if changed or url_changed:
488
491
  path = save_state(state)
489
492
  print(f"Saved {args.provider} credentials to {path}")
490
493
  print(f"Matrx base URL: {ensure_v1_url(state['auth']['matrx']['base_url'])}")
491
494
  return 0
492
- print("Matrx login did not change the current state", file=sys.stderr)
493
- return 1
495
+ if not url_changed:
496
+ print("Matrx login did not change the current state", file=sys.stderr)
497
+ return 1
494
498
 
495
499
  if not key:
496
500
  print("--key is required for this login command", file=sys.stderr)
@@ -585,11 +589,18 @@ def _cmd_status() -> int:
585
589
  print("Active project: none (run: mtrx project switch <name>)")
586
590
 
587
591
  print("Defaults:")
592
+ for tool in ("codex", "claude", "gemini", "cursor"):
593
+ route = configured_route(state, tool) or "not set"
594
+ print(f" {tool}: {route}")
588
595
  print("Auth:")
596
+ config_base = auth["matrx"].get("base_url")
597
+ env_base = (os.environ.get("MATRX_BASE_URL") or "").strip()
598
+ effective_base = ensure_v1_url(env_base or config_base)
599
+ base_source = "MATRX_BASE_URL env" if env_base else "config"
589
600
  print(
590
601
  " matrx: "
591
602
  f"{mask_secret(auth['matrx'].get('key'))} "
592
- f"({ensure_v1_url(auth['matrx'].get('base_url'))})"
603
+ f"({effective_base}) [{base_source}]"
593
604
  )
594
605
  print(f" matrx app: {ensure_app_url(auth['matrx'].get('app_url'), base_url=auth['matrx'].get('base_url'))}")
595
606
  print(f" openai: {mask_secret(auth['openai'].get('key'))}")
@@ -617,6 +628,24 @@ def _cmd_status() -> int:
617
628
  proxy_running = is_proxy_running()
618
629
  print(f" cursor proxy: {'running' if proxy_running else 'not running'}")
619
630
 
631
+ # Matrx API proxy health (when base_url configured)
632
+ base_url = auth["matrx"].get("base_url")
633
+ if base_url:
634
+ try:
635
+ health_url = f"{ensure_root_url(base_url).rstrip('/')}/health/wiring"
636
+ with httpx.Client(timeout=5) as client:
637
+ resp = client.get(health_url)
638
+ if resp.status_code == 200:
639
+ data = resp.json()
640
+ wiring = "ok" if data.get("proxy_wiring_ok") else "incomplete"
641
+ kv = data.get("key_vault", {})
642
+ enc = "configured" if kv.get("encryption_configured") else "not configured"
643
+ print(f" matrx proxy: reachable (wiring={wiring}, key_vault={enc})")
644
+ else:
645
+ print(f" matrx proxy: HTTP {resp.status_code}")
646
+ except Exception as exc:
647
+ print(f" matrx proxy: unreachable ({exc})")
648
+
620
649
  print("Executables:")
621
650
  print(f" codex: {find_executable('codex') or 'not found'}")
622
651
  print(f" claude: {find_executable('claude') or 'not found'}")
@@ -822,6 +851,35 @@ def _cmd_doctor() -> int:
822
851
  else:
823
852
  print(f"[warn] {tool} native config not configured")
824
853
 
854
+ # Proxy health check — when using matrx route, verify server is reachable
855
+ base_url = state.get("auth", {}).get("matrx", {}).get("base_url")
856
+ mx_key = matrx_key or workspace_matrx_key or env_matrx_key
857
+ if base_url and mx_key:
858
+ try:
859
+ health_url = f"{ensure_root_url(base_url).rstrip('/')}/health/wiring"
860
+ with httpx.Client(timeout=10) as client:
861
+ resp = client.get(health_url)
862
+ if resp.status_code == 200:
863
+ data = resp.json()
864
+ if data.get("proxy_wiring_ok"):
865
+ print("[ok] Matrx proxy reachable and wired")
866
+ else:
867
+ comps = data.get("components", {})
868
+ missing = [k for k, v in comps.items() if not v]
869
+ print(f"[warn] Matrx proxy incomplete: missing {missing}")
870
+ kv = data.get("key_vault", {})
871
+ if not kv.get("encryption_configured"):
872
+ print(
873
+ "[warn] Key vault encryption not configured on server — "
874
+ "provider keys may fail to decrypt; set KEY_VAULT_ENCRYPTION_KEY"
875
+ )
876
+ else:
877
+ print(f"[warn] Matrx proxy health check failed: {resp.status_code}")
878
+ except httpx.HTTPError as exc:
879
+ print(f"[warn] Matrx proxy unreachable: {exc}")
880
+ except Exception as exc:
881
+ print(f"[warn] Matrx proxy check failed: {exc}")
882
+
825
883
  return 1 if failures else 0
826
884
 
827
885