conduct-cli 0.4.18__tar.gz → 0.4.20__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: conduct-cli
3
- Version: 0.4.18
3
+ Version: 0.4.20
4
4
  Summary: CLI for Conduct AI — install agents, manage projects, run tests
5
5
  Author-email: Conduct AI <hello@conductai.ai>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "conduct-cli"
7
- version = "0.4.18"
7
+ version = "0.4.20"
8
8
  description = "CLI for Conduct AI — install agents, manage projects, run tests"
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -402,6 +402,20 @@ if __name__ == "__main__":
402
402
  main()
403
403
  '''
404
404
 
405
+ # ── Python interpreter selection ─────────────────────────────────────────────
406
+
407
+ def _best_python() -> str:
408
+ """Return the best available Python 3 interpreter path.
409
+ Prefers 3.11+ (Homebrew) over Apple's system Python 3.9 which has
410
+ restrictions that cause the hook to fail silently."""
411
+ import shutil
412
+ for candidate in ("python3.13", "python3.12", "python3.11", "python3.10"):
413
+ found = shutil.which(candidate)
414
+ if found:
415
+ return found
416
+ return sys.executable
417
+
418
+
405
419
  # ── Hook write helper ─────────────────────────────────────────────────────────
406
420
 
407
421
  def _write_hook(path: Path) -> None:
@@ -502,10 +516,12 @@ def _install_codex_hook(hook_path: Path) -> None:
502
516
  hook_section = hooks.setdefault("hooks", {})
503
517
 
504
518
  # PreToolUse
505
- pre_cmd = f"python3 {hook_path}"
519
+ pre_cmd = f"{_best_python()} {hook_path}"
520
+ hook_path_str = str(hook_path)
506
521
  pre = hook_section.setdefault("PreToolUse", [])
522
+ # Match by hook path so old python3/python3.11 entries are treated as already registered
507
523
  pre_already = any(
508
- e.get("command") == pre_cmd
524
+ hook_path_str in e.get("command", "")
509
525
  for h in pre
510
526
  for e in h.get("hooks", [])
511
527
  )
@@ -513,9 +529,16 @@ def _install_codex_hook(hook_path: Path) -> None:
513
529
  if not pre_already:
514
530
  pre.append({"matcher": ".*", "hooks": [{"type": "command", "command": pre_cmd}]})
515
531
  changed = True
516
-
517
- # PostToolUse self-contained: python3 /path/hook.py post (no PATH dependency)
518
- post_cmd = f"python3 {hook_path} post"
532
+ else:
533
+ # Update existing entry to use current sys.executable
534
+ for h in pre:
535
+ for e in h.get("hooks", []):
536
+ if hook_path_str in e.get("command", "") and e["command"] != pre_cmd:
537
+ e["command"] = pre_cmd
538
+ changed = True
539
+
540
+ # PostToolUse
541
+ post_cmd = f"{_best_python()} {hook_path} post"
519
542
  post = hook_section.setdefault("PostToolUse", [])
520
543
  # Remove stale conductguard-post entries registered by older CLI versions
521
544
  stale = "conductguard-post"
@@ -527,7 +550,7 @@ def _install_codex_hook(hook_path: Path) -> None:
527
550
  cleaned = True
528
551
  post[:] = [h for h in post if h.get("hooks")]
529
552
  post_already = any(
530
- e.get("command") == post_cmd
553
+ hook_path_str in e.get("command", "")
531
554
  for h in post
532
555
  for e in h.get("hooks", [])
533
556
  )
@@ -610,9 +633,10 @@ def _install_claude_hook(hook_path: Path) -> None:
610
633
 
611
634
  # PreToolUse — existing hook script
612
635
  pre = hooks.setdefault("PreToolUse", [])
613
- pre_cmd = f"python3 {hook_path}"
636
+ pre_cmd = f"{_best_python()} {hook_path}"
637
+ hook_path_str = str(hook_path)
614
638
  pre_already = any(
615
- e.get("command") == pre_cmd
639
+ hook_path_str in e.get("command", "")
616
640
  for h in pre
617
641
  for e in h.get("hooks", [])
618
642
  )
@@ -620,10 +644,17 @@ def _install_claude_hook(hook_path: Path) -> None:
620
644
  if not pre_already:
621
645
  pre.append({"matcher": ".*", "hooks": [{"type": "command", "command": pre_cmd}]})
622
646
  changed = True
623
-
624
- # PostToolUse self-contained: python3 /path/hook.py post (no PATH dependency)
647
+ else:
648
+ # Update existing entry to use current sys.executable
649
+ for h in pre:
650
+ for e in h.get("hooks", []):
651
+ if hook_path_str in e.get("command", "") and e["command"] != pre_cmd:
652
+ e["command"] = pre_cmd
653
+ changed = True
654
+
655
+ # PostToolUse
625
656
  post = hooks.setdefault("PostToolUse", [])
626
- post_cmd = f"python3 {hook_path} post"
657
+ post_cmd = f"{_best_python()} {hook_path} post"
627
658
  # Remove stale conductguard-post entries registered by older CLI versions
628
659
  stale = "conductguard-post"
629
660
  cleaned = False
@@ -634,7 +665,7 @@ def _install_claude_hook(hook_path: Path) -> None:
634
665
  cleaned = True
635
666
  post[:] = [h for h in post if h.get("hooks")]
636
667
  post_already = any(
637
- e.get("command") == post_cmd
668
+ hook_path_str in e.get("command", "")
638
669
  for h in post
639
670
  for e in h.get("hooks", [])
640
671
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: conduct-cli
3
- Version: 0.4.18
3
+ Version: 0.4.20
4
4
  Summary: CLI for Conduct AI — install agents, manage projects, run tests
5
5
  Author-email: Conduct AI <hello@conductai.ai>
6
6
  License: MIT
File without changes
File without changes
File without changes