codhc 0.0.1__py3-none-any.whl

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.

Potentially problematic release.


This version of codhc might be problematic. Click here for more details.

codhc/__init__.py ADDED
File without changes
codhc/cli.py ADDED
@@ -0,0 +1,28 @@
1
+ import json
2
+ import sys
3
+ from typing import TextIO
4
+
5
+ from chc.hook_runner import run_hook_command
6
+
7
+
8
+ def run_cli(*, argv: list[str], stdin_text: str) -> tuple[int, str, str]:
9
+ if not argv:
10
+ return (2, "", "Usage: chc <command> [args...]\n")
11
+
12
+ result = run_hook_command(command=argv, stdin_text=stdin_text)
13
+ return (0, f"{json.dumps(result.payload)}\n", result.stderr)
14
+
15
+
16
+ def read_stdin_text(stdin: TextIO) -> str:
17
+ if stdin.isatty():
18
+ return ""
19
+ return stdin.read()
20
+
21
+
22
+ def main() -> None:
23
+ exit_code, stdout_text, stderr_text = run_cli(argv=sys.argv[1:], stdin_text=read_stdin_text(sys.stdin))
24
+ if stderr_text:
25
+ sys.stderr.write(stderr_text)
26
+ if stdout_text:
27
+ sys.stdout.write(stdout_text)
28
+ raise SystemExit(exit_code)
codhc/hook_runner.py ADDED
@@ -0,0 +1,82 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import shlex
5
+ import subprocess
6
+ from dataclasses import dataclass
7
+ from typing import Any
8
+
9
+
10
+ @dataclass(frozen=True)
11
+ class HookResult:
12
+ payload: dict[str, Any]
13
+ stderr: str
14
+
15
+
16
+ def run_hook_command(*, command: list[str], stdin_text: str) -> HookResult:
17
+ stop_hook_active = _parse_stop_hook_active(stdin_text)
18
+ command_display = f"`{shlex.join(command)}`"
19
+ completed = _run_subprocess(command)
20
+
21
+ if completed.returncode == 0:
22
+ return HookResult(
23
+ payload={
24
+ "continue": False,
25
+ "systemMessage": f"{command_display} passed.",
26
+ },
27
+ stderr="",
28
+ )
29
+
30
+ if stop_hook_active:
31
+ return HookResult(
32
+ payload={
33
+ "continue": False,
34
+ "systemMessage": f"{command_display} failed after the Stop continuation pass.",
35
+ },
36
+ stderr=completed.output,
37
+ )
38
+
39
+ return HookResult(
40
+ payload={
41
+ "decision": "block",
42
+ "reason": f"{command_display} failed. Inspect the command output, fix the issues, then stop again.",
43
+ },
44
+ stderr=completed.output,
45
+ )
46
+
47
+
48
+ @dataclass(frozen=True)
49
+ class CommandResult:
50
+ returncode: int
51
+ output: str
52
+
53
+
54
+ def _parse_stop_hook_active(stdin_text: str) -> bool:
55
+ if not stdin_text.strip():
56
+ return False
57
+
58
+ try:
59
+ payload = json.loads(stdin_text)
60
+ except json.JSONDecodeError:
61
+ return False
62
+
63
+ if not isinstance(payload, dict):
64
+ return False
65
+
66
+ return payload.get("stop_hook_active") is True
67
+
68
+
69
+ def _run_subprocess(command: list[str]) -> CommandResult:
70
+ try:
71
+ completed = subprocess.run(
72
+ command,
73
+ check=False,
74
+ stdout=subprocess.PIPE,
75
+ stderr=subprocess.STDOUT,
76
+ text=True,
77
+ )
78
+ except FileNotFoundError as exc:
79
+ missing = exc.filename or command[0]
80
+ return CommandResult(returncode=127, output=f"{missing}: command not found\n")
81
+
82
+ return CommandResult(returncode=completed.returncode, output=completed.stdout)
codhc/py.typed ADDED
File without changes
@@ -0,0 +1,25 @@
1
+ Metadata-Version: 2.3
2
+ Name: codhc
3
+ Version: 0.0.1
4
+ Summary:
5
+ Author: narumi
6
+ Author-email: narumi <toucans-cutouts0f@icloud.com>
7
+ Requires-Dist: typer>=0.24.1
8
+ Requires-Python: >=3.12
9
+ Description-Content-Type: text/markdown
10
+
11
+ # Codex Hook Command
12
+
13
+ `chc` is a small CLI wrapper for Codex hooks. It runs an external command,
14
+ inspects the hook payload from `stdin`, and prints a JSON response that Codex
15
+ can consume.
16
+
17
+ ## Usage
18
+
19
+ ```bash
20
+ chc uv run ruff check --fix
21
+ ```
22
+
23
+ For `Stop` hooks, the first failure returns a continuation payload using the
24
+ legacy `decision: "block"` shape. Success, or failure after the continuation
25
+ pass, returns `continue: false` with a `systemMessage`.
@@ -0,0 +1,8 @@
1
+ codhc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ codhc/cli.py,sha256=moSbp_ejWKIrQiLV8qirx07coY7kMC7PfGIjNeniqFg,768
3
+ codhc/hook_runner.py,sha256=3jEm1nUf_UpwwbOLhMvjGNfoVq-8UBOkXXDmj-ZpHxY,2106
4
+ codhc/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ codhc-0.0.1.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
6
+ codhc-0.0.1.dist-info/entry_points.txt,sha256=PIwrucppW06uEtXHoKgjOL3vNuaeYvuZ0yimsUxlrfo,42
7
+ codhc-0.0.1.dist-info/METADATA,sha256=XaOUoZogmkGs-W55eQoyTa3CNNsPvrzhL7icI8LxtYs,670
8
+ codhc-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.8.24
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ codhc = codhc.cli:main
3
+