claudekit-cli 3.41.4-dev.51 → 3.41.4-dev.52

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/cli-manifest.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "3.41.4-dev.51",
3
- "generatedAt": "2026-04-24T21:03:36.506Z",
2
+ "version": "3.41.4-dev.52",
3
+ "generatedAt": "2026-04-24T21:12:39.210Z",
4
4
  "commands": {
5
5
  "agents": {
6
6
  "name": "agents",
package/dist/index.js CHANGED
@@ -53623,6 +53623,24 @@ function sanitizeOutput(obj, rules) {
53623
53623
  return result;
53624
53624
  }
53625
53625
 
53626
+ /**
53627
+ * True when the given event's scrub rules allow a permissionDecision of "deny".
53628
+ * Used to translate Claude Code's exit-code protocol (exit 2 = block) into
53629
+ * Codex's JSON protocol ({permissionDecision: "deny"}).
53630
+ */
53631
+ function eventSupportsDeny(rules) {
53632
+ if (!rules || rules.allowedPermissionValues === null) return false;
53633
+ return rules.allowedPermissionValues.indexOf("deny") !== -1;
53634
+ }
53635
+
53636
+ function emitDeny(reason) {
53637
+ process.stdout.write(JSON.stringify({
53638
+ permissionDecision: "deny",
53639
+ reason: reason && reason.length > 0 ? reason : "Hook blocked this operation",
53640
+ }));
53641
+ process.exit(0);
53642
+ }
53643
+
53626
53644
  function main() {
53627
53645
  // Collect stdin
53628
53646
  const stdinChunks = [];
@@ -53630,6 +53648,7 @@ function main() {
53630
53648
  process.stdin.on("end", () => {
53631
53649
  const stdinData = Buffer.concat(stdinChunks).toString("utf8");
53632
53650
  const event = getEventFromStdin(stdinData);
53651
+ const rules = event && SCRUB_RULES[event];
53633
53652
 
53634
53653
  // Spawn original hook with same stdin/env
53635
53654
  const result = spawnSync(process.execPath, [ORIGINAL_HOOK], {
@@ -53645,33 +53664,57 @@ function main() {
53645
53664
  process.exit(1);
53646
53665
  }
53647
53666
 
53648
- if (result.stderr) {
53649
- process.stderr.write(result.stderr);
53650
- }
53651
-
53652
- const rawOutput = result.stdout || "";
53667
+ const stderrText = (result.stderr || "").toString();
53668
+ const rawOutput = (result.stdout || "").toString();
53669
+ const exitCode = result.status ?? 1;
53670
+ // Claude Code protocol: exit 2 + stderr = block. Codex expects JSON instead.
53671
+ // Translate only for events where the Codex capability table allows "deny".
53672
+ const isBlockSignal = exitCode === 2 && eventSupportsDeny(rules);
53653
53673
 
53654
- // If the hook produced no JSON output, pass through as-is
53674
+ // No stdout: either silent allow (exit 0) or Claude-style block (exit 2).
53655
53675
  if (!rawOutput.trim()) {
53656
- process.exit(result.status ?? 1);
53676
+ if (isBlockSignal) {
53677
+ return emitDeny(stderrText.trim());
53678
+ }
53679
+ // Non-block failure or plain allow: forward stderr and pass exit code through.
53680
+ if (stderrText) process.stderr.write(stderrText);
53681
+ process.exit(exitCode);
53657
53682
  }
53658
53683
 
53659
- // Try to parse and sanitize JSON output
53684
+ // Try to parse stdout as JSON.
53660
53685
  let parsed;
53661
53686
  try {
53662
53687
  parsed = JSON.parse(rawOutput);
53663
53688
  } catch {
53664
- // Not valid JSON pass through unchanged (Codex may handle it)
53689
+ // Non-JSON stdout. If this is a Claude block signal, treat the stdout
53690
+ // (or stderr) as the deny reason. Otherwise forward unchanged.
53691
+ if (isBlockSignal) {
53692
+ const reason = rawOutput.trim() || stderrText.trim();
53693
+ return emitDeny(reason);
53694
+ }
53695
+ if (stderrText) process.stderr.write(stderrText);
53665
53696
  process.stdout.write(rawOutput);
53666
- process.exit(result.status ?? 1);
53697
+ process.exit(exitCode);
53667
53698
  }
53668
53699
 
53700
+ // Forward stderr for JSON-emitting hooks (diagnostic output). We still
53701
+ // scrub and re-emit the JSON to Codex's stdout.
53702
+ if (stderrText) process.stderr.write(stderrText);
53703
+
53669
53704
  // Apply scrub rules for the detected event
53670
- const rules = event && SCRUB_RULES[event];
53671
53705
  const sanitized = rules ? sanitizeOutput(parsed, rules) : parsed;
53672
53706
 
53707
+ // If the hook signalled block via exit 2 but didn't emit a deny decision
53708
+ // in the JSON, translate — otherwise Codex ignores the exit code.
53709
+ if (isBlockSignal && (!sanitized || sanitized.permissionDecision !== "deny")) {
53710
+ return emitDeny(stderrText.trim());
53711
+ }
53712
+
53673
53713
  process.stdout.write(JSON.stringify(sanitized));
53674
- process.exit(result.status ?? 1);
53714
+ // When the hook already emitted a valid deny JSON but also exited 2,
53715
+ // exit 0 so Codex treats the deny as authoritative (consistent with
53716
+ // emitDeny's exit-0 contract).
53717
+ process.exit(isBlockSignal ? 0 : exitCode);
53675
53718
  });
53676
53719
  }
53677
53720
 
@@ -62203,7 +62246,7 @@ var package_default;
62203
62246
  var init_package = __esm(() => {
62204
62247
  package_default = {
62205
62248
  name: "claudekit-cli",
62206
- version: "3.41.4-dev.51",
62249
+ version: "3.41.4-dev.52",
62207
62250
  description: "CLI tool for bootstrapping and updating ClaudeKit projects",
62208
62251
  type: "module",
62209
62252
  repository: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudekit-cli",
3
- "version": "3.41.4-dev.51",
3
+ "version": "3.41.4-dev.52",
4
4
  "description": "CLI tool for bootstrapping and updating ClaudeKit projects",
5
5
  "type": "module",
6
6
  "repository": {