oh-my-customcode 1.1.54 → 1.1.56
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/dist/cli/index.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/templates/.claude/hooks/hooks.json +19 -19
- package/templates/.claude/hooks/scripts/agent-start-recorder.sh +5 -5
- package/templates/.claude/hooks/scripts/agent-teams-advisor.sh +4 -4
- package/templates/.claude/hooks/scripts/audit-log.sh +6 -6
- package/templates/.claude/hooks/scripts/auto-continue-guard.sh +1 -1
- package/templates/.claude/hooks/scripts/auto-dev-token-summary.sh +6 -6
- package/templates/.claude/hooks/scripts/auto-dev-token-tracker.sh +6 -6
- package/templates/.claude/hooks/scripts/content-hash-validator.sh +4 -4
- package/templates/.claude/hooks/scripts/context-budget-advisor.sh +3 -3
- package/templates/.claude/hooks/scripts/cost-cap-advisor.sh +6 -6
- package/templates/.claude/hooks/scripts/cwd-change-detector.sh +3 -3
- package/templates/.claude/hooks/scripts/destructive-git-guard.sh +2 -2
- package/templates/.claude/hooks/scripts/eval-core-batch-save.sh +2 -2
- package/templates/.claude/hooks/scripts/feedback-collector.sh +7 -7
- package/templates/.claude/hooks/scripts/file-change-validator.sh +4 -4
- package/templates/.claude/hooks/scripts/git-delegation-guard.sh +3 -3
- package/templates/.claude/hooks/scripts/model-escalation-advisor.sh +4 -4
- package/templates/.claude/hooks/scripts/omcustom-auto-update.sh +6 -6
- package/templates/.claude/hooks/scripts/playwright-compress.sh +4 -4
- package/templates/.claude/hooks/scripts/plugin-cache-check.sh +2 -2
- package/templates/.claude/hooks/scripts/r007-r008-drift-advisor.sh +26 -3
- package/templates/.claude/hooks/scripts/rtk-intercept.sh +9 -9
- package/templates/.claude/hooks/scripts/rule-deletion-guard.sh +5 -5
- package/templates/.claude/hooks/scripts/schema-validator.sh +10 -10
- package/templates/.claude/hooks/scripts/secret-filter.sh +4 -4
- package/templates/.claude/hooks/scripts/session-autofix-prompt.sh +3 -3
- package/templates/.claude/hooks/scripts/session-autofix.sh +1 -1
- package/templates/.claude/hooks/scripts/session-env-check.sh +1 -1
- package/templates/.claude/hooks/scripts/session-reflection.sh +15 -15
- package/templates/.claude/hooks/scripts/skill-extractor-analyzer.sh +2 -2
- package/templates/.claude/hooks/scripts/stale-todo-scanner.sh +1 -1
- package/templates/.claude/hooks/scripts/stall-detection-advisor.sh +11 -11
- package/templates/.claude/hooks/scripts/stop-console-audit.sh +1 -1
- package/templates/.claude/hooks/scripts/stuck-detector.sh +81 -25
- package/templates/.claude/hooks/scripts/subagent-failure-advisor.sh +36 -0
- package/templates/.claude/hooks/scripts/task-outcome-recorder.sh +8 -8
- package/templates/.claude/hooks/scripts/task-state-precompact.sh +1 -1
- package/templates/.claude/settings.json +19 -19
- package/templates/manifest.json +1 -1
package/dist/cli/index.js
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"hooks": [
|
|
18
18
|
{
|
|
19
19
|
"type": "command",
|
|
20
|
-
"command": "#!/bin/bash\ninput=$(cat)\ncmd=$(
|
|
20
|
+
"command": "#!/bin/bash\ninput=$(cat)\ncmd=$(printf '%s\\n' \"$input\" | jq -r '.tool_input.command // \"\"')\n\n# Block dev servers that aren't run in tmux\necho '[Hook] BLOCKED: Dev server must run in tmux for log access' >&2\necho '[Hook] Use this command instead:' >&2\necho \"[Hook] tmux new-session -d -s dev 'npm run dev'\" >&2\necho '[Hook] Then: tmux attach -t dev' >&2\nexit 1"
|
|
21
21
|
}
|
|
22
22
|
],
|
|
23
23
|
"description": "Block dev servers outside tmux - ensures you can access logs"
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"hooks": [
|
|
28
28
|
{
|
|
29
29
|
"type": "command",
|
|
30
|
-
"command": "#!/bin/bash\ninput=$(cat)\nif [ -z \"$TMUX\" ]; then\n echo '[Hook] Consider running in tmux for session persistence' >&2\n echo '[Hook] tmux new -s dev | tmux attach -t dev' >&2\nfi\
|
|
30
|
+
"command": "#!/bin/bash\ninput=$(cat)\nif [ -z \"$TMUX\" ]; then\n echo '[Hook] Consider running in tmux for session persistence' >&2\n echo '[Hook] tmux new -s dev | tmux attach -t dev' >&2\nfi\nprintf '%s\\n' \"$input\""
|
|
31
31
|
}
|
|
32
32
|
],
|
|
33
33
|
"description": "Reminder to use tmux for long-running commands"
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"hooks": [
|
|
48
48
|
{
|
|
49
49
|
"type": "command",
|
|
50
|
-
"command": "#!/bin/bash\ninput=$(cat)\nfile_path=$(
|
|
50
|
+
"command": "#!/bin/bash\ninput=$(cat)\nfile_path=$(printf '%s\\n' \"$input\" | jq -r '.tool_input.file_path // \"\"')\n\nif [[ \"$file_path\" =~ \\.(md|txt)$ ]] && [[ ! \"$file_path\" =~ (README|CLAUDE|AGENT|SKILL)\\.md$ ]]; then\n echo \"[Hook] BLOCKED: Unnecessary documentation file creation\" >&2\n echo \"[Hook] File: $file_path\" >&2\n echo \"[Hook] Use README.md or AGENT.md for documentation instead\" >&2\n exit 1\nfi\n\nprintf '%s\\n' \"$input\""
|
|
51
51
|
}
|
|
52
52
|
],
|
|
53
53
|
"description": "Block creation of random .md files - keeps docs consolidated"
|
|
@@ -117,7 +117,7 @@
|
|
|
117
117
|
"hooks": [
|
|
118
118
|
{
|
|
119
119
|
"type": "command",
|
|
120
|
-
"command": "#!/bin/bash\ninput=$(cat)\nagent_type=$(
|
|
120
|
+
"command": "#!/bin/bash\ninput=$(cat)\nagent_type=$(printf '%s\\n' \"$input\" | jq -r '.tool_input.subagent_type // \"unknown\"')\nmodel=$(printf '%s\\n' \"$input\" | jq -r '.tool_input.model // \"inherit\"')\ndesc=$(printf '%s\\n' \"$input\" | jq -r '.tool_input.description // \"\"' | head -c 40)\nresume=$(printf '%s\\n' \"$input\" | jq -r '.tool_input.resume // empty')\nif [ -n \"$resume\" ]; then\n echo \"─── [Resume] ${agent_type}:${model} | ${desc} ───\" >&2\nelse\n echo \"─── [Spawn] ${agent_type}:${model} | ${desc} ───\" >&2\nfi\nprintf '%s\\n' \"$input\""
|
|
121
121
|
},
|
|
122
122
|
{
|
|
123
123
|
"type": "command",
|
|
@@ -255,7 +255,7 @@
|
|
|
255
255
|
"hooks": [
|
|
256
256
|
{
|
|
257
257
|
"type": "command",
|
|
258
|
-
"command": "#!/bin/bash\ninput=$(cat)\nagent_type=$(
|
|
258
|
+
"command": "#!/bin/bash\ninput=$(cat)\nagent_type=$(printf '%s\\n' \"$input\" | jq -r '.agent_type // \"unknown\"')\nmodel=$(printf '%s\\n' \"$input\" | jq -r '.model // \"inherit\"')\ndesc=$(printf '%s\\n' \"$input\" | jq -r '.description // \"\"' | head -c 40)\necho \"─── [SubagentStart] ${agent_type}:${model} | ${desc} ───\" >&2\nprintf '%s\\n' \"$input\""
|
|
259
259
|
},
|
|
260
260
|
{
|
|
261
261
|
"type": "command",
|
|
@@ -286,11 +286,11 @@
|
|
|
286
286
|
"command": "bash .claude/hooks/scripts/r007-r008-drift-advisor.sh"
|
|
287
287
|
},
|
|
288
288
|
{
|
|
289
|
-
"type": "
|
|
290
|
-
"
|
|
289
|
+
"type": "command",
|
|
290
|
+
"command": "bash .claude/hooks/scripts/subagent-failure-advisor.sh"
|
|
291
291
|
}
|
|
292
292
|
],
|
|
293
|
-
"description": "Record agent outcomes + auto-continue workflow + R007/R008 drift advisory on subagent completion (autonomous-loop re-entry, #1545)"
|
|
293
|
+
"description": "Record agent outcomes + auto-continue workflow + R007/R008 drift advisory + failure advisory on subagent completion (autonomous-loop re-entry, #1545; #1631 replaced the self-referential prompt-type judge hook with an advisory-only command hook)"
|
|
294
294
|
}
|
|
295
295
|
],
|
|
296
296
|
"CwdChanged": [
|
|
@@ -323,7 +323,7 @@
|
|
|
323
323
|
"hooks": [
|
|
324
324
|
{
|
|
325
325
|
"type": "command",
|
|
326
|
-
"command": "#!/bin/bash\ninput=$(cat)\nmsg=$(
|
|
326
|
+
"command": "#!/bin/bash\ninput=$(cat)\nmsg=$(printf '%s\\n' \"$input\" | jq -r '.message // \"\"' 2>/dev/null)\nif [ -n \"$msg\" ]; then\n echo \"[Hook] Notification: $msg\" >&2\nfi\nprintf '%s\\n' \"$input\""
|
|
327
327
|
}
|
|
328
328
|
],
|
|
329
329
|
"description": "Display notifications for long-running operation completions"
|
|
@@ -335,7 +335,7 @@
|
|
|
335
335
|
"hooks": [
|
|
336
336
|
{
|
|
337
337
|
"type": "command",
|
|
338
|
-
"command": "#!/bin/bash\ninput=$(cat)\nteammate=$(
|
|
338
|
+
"command": "#!/bin/bash\ninput=$(cat)\nteammate=$(printf '%s\\n' \"$input\" | jq -r '.teammate_id // \"unknown\"' 2>/dev/null)\necho \"[Hook] TeammateIdle: $teammate — available for reassignment\" >&2\nprintf '%s\\n' \"$input\""
|
|
339
339
|
}
|
|
340
340
|
],
|
|
341
341
|
"description": "Track idle Agent Teams members for work reassignment"
|
|
@@ -347,7 +347,7 @@
|
|
|
347
347
|
"hooks": [
|
|
348
348
|
{
|
|
349
349
|
"type": "command",
|
|
350
|
-
"command": "#!/bin/bash\ninput=$(cat)\ntask_id=$(
|
|
350
|
+
"command": "#!/bin/bash\ninput=$(cat)\ntask_id=$(printf '%s\\n' \"$input\" | jq -r '.task_id // \"\"' 2>/dev/null)\ndesc=$(printf '%s\\n' \"$input\" | jq -r '.description // \"\"' 2>/dev/null | head -c 60)\necho \"[Hook] TaskCreated: $task_id — $desc\" >&2\nprintf '%s\\n' \"$input\""
|
|
351
351
|
}
|
|
352
352
|
],
|
|
353
353
|
"description": "Log task creation events for Agent Teams coordination"
|
|
@@ -359,7 +359,7 @@
|
|
|
359
359
|
"hooks": [
|
|
360
360
|
{
|
|
361
361
|
"type": "command",
|
|
362
|
-
"command": "#!/bin/bash\ninput=$(cat)\ntask_id=$(
|
|
362
|
+
"command": "#!/bin/bash\ninput=$(cat)\ntask_id=$(printf '%s\\n' \"$input\" | jq -r '.task_id // \"\"' 2>/dev/null)\nresult=$(printf '%s\\n' \"$input\" | jq -r '.result // \"\"' 2>/dev/null | head -c 60)\necho \"[Hook] TaskCompleted: $task_id — $result\" >&2\nprintf '%s\\n' \"$input\""
|
|
363
363
|
}
|
|
364
364
|
],
|
|
365
365
|
"description": "Log task completion events for Agent Teams coordination"
|
|
@@ -395,7 +395,7 @@
|
|
|
395
395
|
"hooks": [
|
|
396
396
|
{
|
|
397
397
|
"type": "command",
|
|
398
|
-
"command": "#!/bin/bash\ninput=$(cat)\ncmd=$(
|
|
398
|
+
"command": "#!/bin/bash\ninput=$(cat)\ncmd=$(printf '%s\\n' \"$input\" | jq -r '.tool_input.command')\n\nif echo \"$cmd\" | grep -qE 'gh pr create'; then\n output=$(printf '%s\\n' \"$input\" | jq -r '.tool_output.output // \"\"')\n pr_url=$(echo \"$output\" | grep -oE 'https://github.com/[^/]+/[^/]+/pull/[0-9]+')\n \n if [ -n \"$pr_url\" ]; then\n echo \"[Hook] PR created: $pr_url\" >&2\n echo \"[Hook] Checking GitHub Actions status...\" >&2\n repo=$(echo \"$pr_url\" | sed -E 's|https://github.com/([^/]+/[^/]+)/pull/[0-9]+|\\1|')\n pr_num=$(echo \"$pr_url\" | sed -E 's|.*/pull/([0-9]+)|\\1|')\n echo \"[Hook] To review PR: gh pr review $pr_num --repo $repo\" >&2\n fi\nfi\n\nprintf '%s\\n' \"$input\""
|
|
399
399
|
}
|
|
400
400
|
],
|
|
401
401
|
"description": "Log PR URL and provide review command after PR creation"
|
|
@@ -405,7 +405,7 @@
|
|
|
405
405
|
"hooks": [
|
|
406
406
|
{
|
|
407
407
|
"type": "command",
|
|
408
|
-
"command": "#!/bin/bash\ninput=$(cat)\nfile_path=$(
|
|
408
|
+
"command": "#!/bin/bash\ninput=$(cat)\nfile_path=$(printf '%s\\n' \"$input\" | jq -r '.tool_input.file_path // \"\"')\n\nif [ -n \"$file_path\" ] && [ -f \"$file_path\" ]; then\n if command -v prettier >/dev/null 2>&1; then\n prettier --write \"$file_path\" 2>&1 | head -5 >&2\n fi\nfi\n\nprintf '%s\\n' \"$input\""
|
|
409
409
|
}
|
|
410
410
|
],
|
|
411
411
|
"description": "Auto-format JS/TS files with Prettier after edits"
|
|
@@ -415,7 +415,7 @@
|
|
|
415
415
|
"hooks": [
|
|
416
416
|
{
|
|
417
417
|
"type": "command",
|
|
418
|
-
"command": "#!/bin/bash\ninput=$(cat)\nfile_path=$(
|
|
418
|
+
"command": "#!/bin/bash\ninput=$(cat)\nfile_path=$(printf '%s\\n' \"$input\" | jq -r '.tool_input.file_path // \"\"')\n\nif [ -n \"$file_path\" ] && [ -f \"$file_path\" ]; then\n dir=$(dirname \"$file_path\")\n project_root=\"$dir\"\n while [ \"$project_root\" != \"/\" ] && [ ! -f \"$project_root/package.json\" ]; do\n project_root=$(dirname \"$project_root\")\n done\n \n if [ -f \"$project_root/tsconfig.json\" ]; then\n cd \"$project_root\" && npx tsc --noEmit --pretty false 2>&1 | grep \"$file_path\" | head -10 >&2 || true\n fi\nfi\n\nprintf '%s\\n' \"$input\"",
|
|
419
419
|
"continueOnBlock": true
|
|
420
420
|
}
|
|
421
421
|
],
|
|
@@ -426,7 +426,7 @@
|
|
|
426
426
|
"hooks": [
|
|
427
427
|
{
|
|
428
428
|
"type": "command",
|
|
429
|
-
"command": "#!/bin/bash\ninput=$(cat)\nfile_path=$(
|
|
429
|
+
"command": "#!/bin/bash\ninput=$(cat)\nfile_path=$(printf '%s\\n' \"$input\" | jq -r '.tool_input.file_path // \"\"')\n\nif [ -n \"$file_path\" ] && [ -f \"$file_path\" ]; then\n console_logs=$(grep -n \"console\\\\.log\" \"$file_path\" 2>/dev/null || true)\n \n if [ -n \"$console_logs\" ]; then\n echo \"[Hook] WARNING: console.log found in $file_path\" >&2\n echo \"$console_logs\" | head -5 >&2\n echo \"[Hook] Remove console.log before committing\" >&2\n fi\nfi\n\nprintf '%s\\n' \"$input\"",
|
|
430
430
|
"continueOnBlock": true
|
|
431
431
|
}
|
|
432
432
|
],
|
|
@@ -437,7 +437,7 @@
|
|
|
437
437
|
"hooks": [
|
|
438
438
|
{
|
|
439
439
|
"type": "command",
|
|
440
|
-
"command": "#!/bin/bash\ninput=$(cat)\nfile_path=$(
|
|
440
|
+
"command": "#!/bin/bash\ninput=$(cat)\nfile_path=$(printf '%s\\n' \"$input\" | jq -r '.tool_input.file_path // \"\"')\n\nif [ -n \"$file_path\" ] && [ -f \"$file_path\" ]; then\n if command -v gofmt >/dev/null 2>&1; then\n gofmt -w \"$file_path\" 2>&1 >&2\n fi\nfi\n\nprintf '%s\\n' \"$input\""
|
|
441
441
|
}
|
|
442
442
|
],
|
|
443
443
|
"description": "Auto-format Go files with gofmt after edits"
|
|
@@ -447,7 +447,7 @@
|
|
|
447
447
|
"hooks": [
|
|
448
448
|
{
|
|
449
449
|
"type": "command",
|
|
450
|
-
"command": "#!/bin/bash\ninput=$(cat)\nfile_path=$(
|
|
450
|
+
"command": "#!/bin/bash\ninput=$(cat)\nfile_path=$(printf '%s\\n' \"$input\" | jq -r '.tool_input.file_path // \"\"')\n\nif [ -n \"$file_path\" ] && [ -f \"$file_path\" ]; then\n # Format with ruff\n if command -v ruff >/dev/null 2>&1; then\n ruff format --quiet \"$file_path\" 2>&1 >&2\n ruff check --fix --quiet \"$file_path\" 2>&1 >&2 || true\n echo \"[Hook] Python formatted with ruff\" >&2\n fi\nfi\n\nprintf '%s\\n' \"$input\"",
|
|
451
451
|
"continueOnBlock": true
|
|
452
452
|
}
|
|
453
453
|
],
|
|
@@ -458,7 +458,7 @@
|
|
|
458
458
|
"hooks": [
|
|
459
459
|
{
|
|
460
460
|
"type": "command",
|
|
461
|
-
"command": "#!/bin/bash\ninput=$(cat)\nfile_path=$(
|
|
461
|
+
"command": "#!/bin/bash\ninput=$(cat)\nfile_path=$(printf '%s\\n' \"$input\" | jq -r '.tool_input.file_path // \"\"')\n\nif [ -n \"$file_path\" ] && [ -f \"$file_path\" ]; then\n # Type check with ty\n if command -v ty >/dev/null 2>&1; then\n dir=$(dirname \"$file_path\")\n project_root=\"$dir\"\n while [ \"$project_root\" != \"/\" ] && [ ! -f \"$project_root/pyproject.toml\" ]; do\n project_root=$(dirname \"$project_root\")\n done\n \n if [ -f \"$project_root/pyproject.toml\" ]; then\n cd \"$project_root\" && ty check \"$file_path\" 2>&1 | head -10 >&2 || true\n else\n ty check \"$file_path\" 2>&1 | head -10 >&2 || true\n fi\n fi\nfi\n\nprintf '%s\\n' \"$input\"",
|
|
462
462
|
"continueOnBlock": true
|
|
463
463
|
}
|
|
464
464
|
],
|
|
@@ -10,9 +10,9 @@ command -v jq >/dev/null 2>&1 || { cat; exit 0; }
|
|
|
10
10
|
|
|
11
11
|
input=$(cat)
|
|
12
12
|
|
|
13
|
-
agent_type=$(
|
|
14
|
-
model=$(
|
|
15
|
-
description=$(
|
|
13
|
+
agent_type=$(printf '%s\n' "$input" | jq -r '.agent_type // "unknown"')
|
|
14
|
+
model=$(printf '%s\n' "$input" | jq -r '.model // "inherit"')
|
|
15
|
+
description=$(printf '%s\n' "$input" | jq -r '.description // ""' | head -c 80)
|
|
16
16
|
|
|
17
17
|
AGENT_START_FILE="/tmp/.claude-agent-starts-${PPID}"
|
|
18
18
|
|
|
@@ -25,7 +25,7 @@ entry=$(jq -cn \
|
|
|
25
25
|
--arg desc "$description" \
|
|
26
26
|
'{start_epoch: $ts, agent_type: $agent, model: $model, description: $desc}')
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
printf '%s\n' "$entry" >> "$AGENT_START_FILE"
|
|
29
29
|
|
|
30
30
|
# Ring buffer: 50 max
|
|
31
31
|
if [ -f "$AGENT_START_FILE" ]; then
|
|
@@ -36,5 +36,5 @@ if [ -f "$AGENT_START_FILE" ]; then
|
|
|
36
36
|
fi
|
|
37
37
|
fi
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
printf '%s\n' "$input"
|
|
40
40
|
exit 0
|
|
@@ -21,7 +21,7 @@ ENV_STATUS="/tmp/.claude-env-status-${PPID}"
|
|
|
21
21
|
if [ -f "$ENV_STATUS" ]; then
|
|
22
22
|
teams_status=$(grep "agent_teams=" "$ENV_STATUS" 2>/dev/null | cut -d= -f2 || echo "unknown")
|
|
23
23
|
if [ "$teams_status" != "enabled" ]; then
|
|
24
|
-
|
|
24
|
+
printf '%s\n' "$input"
|
|
25
25
|
exit 0
|
|
26
26
|
fi
|
|
27
27
|
fi
|
|
@@ -43,8 +43,8 @@ if [ -f "$RELEASE_PLAN" ]; then
|
|
|
43
43
|
fi
|
|
44
44
|
|
|
45
45
|
# Extract task info from input
|
|
46
|
-
agent_type=$(
|
|
47
|
-
prompt_preview=$(
|
|
46
|
+
agent_type=$(printf '%s\n' "$input" | jq -r '.tool_input.subagent_type // "unknown"')
|
|
47
|
+
prompt_preview=$(printf '%s\n' "$input" | jq -r '.tool_input.description // ""' | head -c 60)
|
|
48
48
|
|
|
49
49
|
# Session-scoped counter using parent PID as session identifier
|
|
50
50
|
COUNTER_FILE="/tmp/.claude-task-count-${PPID}"
|
|
@@ -77,5 +77,5 @@ elif [ "$COUNT" -ge 2 ]; then
|
|
|
77
77
|
fi
|
|
78
78
|
|
|
79
79
|
# Always pass through -- advisory only, never blocks
|
|
80
|
-
|
|
80
|
+
printf '%s\n' "$input"
|
|
81
81
|
exit 0
|
|
@@ -14,11 +14,11 @@ command -v jq >/dev/null 2>&1 || exit 0
|
|
|
14
14
|
input=$(cat)
|
|
15
15
|
|
|
16
16
|
# Extract fields from hook input
|
|
17
|
-
tool_name=$(
|
|
18
|
-
file_path=$(
|
|
19
|
-
agent_type=$(
|
|
20
|
-
model=$(
|
|
21
|
-
is_error=$(
|
|
17
|
+
tool_name=$(printf '%s\n' "$input" | jq -r '.tool_name // "unknown"')
|
|
18
|
+
file_path=$(printf '%s\n' "$input" | jq -r '.tool_input.file_path // .tool_input.command // ""' | head -c 200)
|
|
19
|
+
agent_type=$(printf '%s\n' "$input" | jq -r '.agent_type // "unknown"')
|
|
20
|
+
model=$(printf '%s\n' "$input" | jq -r '.model // "unknown"')
|
|
21
|
+
is_error=$(printf '%s\n' "$input" | jq -r '.tool_output.is_error // false')
|
|
22
22
|
timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
23
23
|
|
|
24
24
|
# Determine outcome
|
|
@@ -55,7 +55,7 @@ if [ -f "$AUDIT_LOG" ]; then
|
|
|
55
55
|
fi
|
|
56
56
|
|
|
57
57
|
# Pass through
|
|
58
|
-
|
|
58
|
+
printf '%s\n' "$input"
|
|
59
59
|
HOOK_END=$(date +%s%N 2>/dev/null || echo 0)
|
|
60
60
|
if [ "$HOOK_START" != "0" ] && [ "$HOOK_END" != "0" ]; then
|
|
61
61
|
HOOK_MS=$(( (HOOK_END - HOOK_START) / 1000000 ))
|
|
@@ -32,7 +32,7 @@ summary=$(jq -s -r '
|
|
|
32
32
|
[ "$summary" = "[]" ] && exit 0
|
|
33
33
|
|
|
34
34
|
# Totals
|
|
35
|
-
totals=$(
|
|
35
|
+
totals=$(printf '%s\n' "$summary" | jq -r '
|
|
36
36
|
{
|
|
37
37
|
total_calls: (map(.calls) | add),
|
|
38
38
|
total_in: (map(.tokens_in) | add),
|
|
@@ -40,10 +40,10 @@ totals=$(echo "$summary" | jq -r '
|
|
|
40
40
|
grand: (map(.total) | add)
|
|
41
41
|
}
|
|
42
42
|
')
|
|
43
|
-
total_calls=$(
|
|
44
|
-
total_in=$(
|
|
45
|
-
total_out=$(
|
|
46
|
-
grand=$(
|
|
43
|
+
total_calls=$(printf '%s\n' "$totals" | jq -r '.total_calls')
|
|
44
|
+
total_in=$(printf '%s\n' "$totals" | jq -r '.total_in')
|
|
45
|
+
total_out=$(printf '%s\n' "$totals" | jq -r '.total_out')
|
|
46
|
+
grand=$(printf '%s\n' "$totals" | jq -r '.grand')
|
|
47
47
|
|
|
48
48
|
{
|
|
49
49
|
echo ""
|
|
@@ -52,7 +52,7 @@ grand=$(echo "$totals" | jq -r '.grand')
|
|
|
52
52
|
echo ""
|
|
53
53
|
printf "| %-32s | %5s | %10s | %10s | %10s |\n" "Phase" "Calls" "Tokens In" "Tokens Out" "Total"
|
|
54
54
|
printf "| %-32s | %5s | %10s | %10s | %10s |\n" "--------------------------------" "-----" "----------" "----------" "----------"
|
|
55
|
-
|
|
55
|
+
printf '%s\n' "$summary" | jq -r '.[] | "\(.phase)\t\(.calls)\t\(.tokens_in)\t\(.tokens_out)\t\(.total)"' | \
|
|
56
56
|
while IFS=$'\t' read -r phase calls tin tout tot; do
|
|
57
57
|
phase_trunc=$(printf "%s" "$phase" | head -c 32)
|
|
58
58
|
printf "| %-32s | %5s | %10s | %10s | %10s |\n" "$phase_trunc" "$calls" "$tin" "$tout" "$tot"
|
|
@@ -9,7 +9,7 @@ set -euo pipefail
|
|
|
9
9
|
|
|
10
10
|
# Always pass through input no matter what
|
|
11
11
|
input=$(cat)
|
|
12
|
-
trap '
|
|
12
|
+
trap 'printf "%s\n" "$input"' EXIT
|
|
13
13
|
|
|
14
14
|
# Gate: only active during auto-dev pipeline
|
|
15
15
|
PIPELINE_STATE="/tmp/.claude-pipeline-auto-dev-${PPID}.json"
|
|
@@ -21,10 +21,10 @@ command -v jq >/dev/null 2>&1 || exit 0
|
|
|
21
21
|
LOG_FILE="/tmp/auto-dev-spend-${PPID}.json"
|
|
22
22
|
|
|
23
23
|
# Extract fields (PostToolUse Agent shape)
|
|
24
|
-
agent_type=$(
|
|
25
|
-
description=$(
|
|
26
|
-
prompt_text=$(
|
|
27
|
-
output_text=$(
|
|
24
|
+
agent_type=$(printf '%s\n' "$input" | jq -r '.tool_input.subagent_type // "unknown"' 2>/dev/null || echo "unknown")
|
|
25
|
+
description=$(printf '%s\n' "$input" | jq -r '.tool_input.description // ""' 2>/dev/null || echo "")
|
|
26
|
+
prompt_text=$(printf '%s\n' "$input" | jq -r '.tool_input.prompt // ""' 2>/dev/null || echo "")
|
|
27
|
+
output_text=$(printf '%s\n' "$input" | jq -r '.tool_output.output // .tool_output // ""' 2>/dev/null || echo "")
|
|
28
28
|
|
|
29
29
|
# Derive phase from pipeline state (current_phase) or fallback to description prefix
|
|
30
30
|
phase=$(jq -r '.current_phase // .phase // "unknown"' "$PIPELINE_STATE" 2>/dev/null || echo "unknown")
|
|
@@ -52,6 +52,6 @@ entry=$(jq -n -c \
|
|
|
52
52
|
--argjson tout "$tokens_out" \
|
|
53
53
|
'{ts: $ts, phase: $phase, agent: $agent, tokens_in: $tin, tokens_out: $tout}' 2>/dev/null) || exit 0
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
printf '%s\n' "$entry" >> "$LOG_FILE" 2>/dev/null || true
|
|
56
56
|
|
|
57
57
|
exit 0
|
|
@@ -15,12 +15,12 @@ input=$(cat)
|
|
|
15
15
|
# Hash store (PPID-scoped, session-only)
|
|
16
16
|
HASH_STORE="/tmp/.claude-content-hashes-${PPID}"
|
|
17
17
|
|
|
18
|
-
tool_name=$(
|
|
18
|
+
tool_name=$(printf '%s\n' "$input" | jq -r '.tool_name // "unknown"')
|
|
19
19
|
|
|
20
20
|
case "$tool_name" in
|
|
21
21
|
"Read")
|
|
22
22
|
# Store content hash for the file that was just read
|
|
23
|
-
file_path=$(
|
|
23
|
+
file_path=$(printf '%s\n' "$input" | jq -r '.tool_input.file_path // ""')
|
|
24
24
|
|
|
25
25
|
if [ -n "$file_path" ] && [ -f "$file_path" ]; then
|
|
26
26
|
content_hash=$(md5 -q "$file_path" 2>/dev/null || md5sum "$file_path" 2>/dev/null | cut -d' ' -f1 || echo "unknown")
|
|
@@ -43,7 +43,7 @@ case "$tool_name" in
|
|
|
43
43
|
|
|
44
44
|
"Edit")
|
|
45
45
|
# Validate that file hasn't changed since last Read
|
|
46
|
-
file_path=$(
|
|
46
|
+
file_path=$(printf '%s\n' "$input" | jq -r '.tool_input.file_path // ""')
|
|
47
47
|
|
|
48
48
|
if [ -n "$file_path" ] && [ -f "$HASH_STORE" ] && [ -f "$file_path" ]; then
|
|
49
49
|
stored_hash=$(grep "\"path\":\"${file_path}\"" "$HASH_STORE" 2>/dev/null | tail -1 | jq -r '.hash // ""' 2>/dev/null || echo "")
|
|
@@ -71,5 +71,5 @@ if [ -f "$HASH_STORE" ]; then
|
|
|
71
71
|
fi
|
|
72
72
|
|
|
73
73
|
# Always pass through
|
|
74
|
-
|
|
74
|
+
printf '%s\n' "$input"
|
|
75
75
|
exit 0
|
|
@@ -33,7 +33,7 @@ read_count=${read_count:-0}
|
|
|
33
33
|
agent_count=${agent_count:-0}
|
|
34
34
|
|
|
35
35
|
# Determine tool type from input
|
|
36
|
-
TOOL=$(
|
|
36
|
+
TOOL=$(printf '%s\n' "$input" | jq -r '.tool_name // ""' 2>/dev/null || echo "")
|
|
37
37
|
tool_count=$((tool_count + 1))
|
|
38
38
|
|
|
39
39
|
case "$TOOL" in
|
|
@@ -95,7 +95,7 @@ if [ "$tool_count" -ge "$THRESHOLD" ] && [ ! -f "$BLOCK_FILE" ]; then
|
|
|
95
95
|
HOOK_MS=$(( (HOOK_END - HOOK_START) / 1000000 ))
|
|
96
96
|
echo "[Hook Perf] $(basename "$0"): ${HOOK_MS}ms" >> "/tmp/.claude-hook-perf-${PPID}.log"
|
|
97
97
|
fi
|
|
98
|
-
|
|
98
|
+
printf '%s\n' "$input"
|
|
99
99
|
exit 2
|
|
100
100
|
fi
|
|
101
101
|
|
|
@@ -112,7 +112,7 @@ if [ "$tool_count" -gt 0 ] && [ $((tool_count % 50)) -eq 0 ]; then
|
|
|
112
112
|
fi
|
|
113
113
|
|
|
114
114
|
# Pass through
|
|
115
|
-
|
|
115
|
+
printf '%s\n' "$input"
|
|
116
116
|
HOOK_END=$(date +%s%N 2>/dev/null || echo 0)
|
|
117
117
|
if [ "$HOOK_START" != "0" ] && [ "$HOOK_END" != "0" ]; then
|
|
118
118
|
HOOK_MS=$(( (HOOK_END - HOOK_START) / 1000000 ))
|
|
@@ -15,19 +15,19 @@ COST_CAP="${CLAUDE_COST_CAP:-5.00}"
|
|
|
15
15
|
|
|
16
16
|
# Check if cost data is available
|
|
17
17
|
if [ ! -f "$COST_FILE" ]; then
|
|
18
|
-
|
|
18
|
+
printf '%s\n' "$input"
|
|
19
19
|
exit 0
|
|
20
20
|
fi
|
|
21
21
|
|
|
22
22
|
# TSV: cost_usd, ctx_pct, timestamp, rl_5h_pct, rl_7d_pct, rl_5h_resets, rl_7d_resets
|
|
23
23
|
IFS=$'\t' read -r cost_usd ctx_pct timestamp _rl_5h _rl_7d _rl_5h_resets _rl_7d_resets < "$COST_FILE" 2>/dev/null || {
|
|
24
|
-
|
|
24
|
+
printf '%s\n' "$input"
|
|
25
25
|
exit 0
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
# Validate cost_usd is a number
|
|
29
29
|
if ! printf '%f' "$cost_usd" >/dev/null 2>&1; then
|
|
30
|
-
|
|
30
|
+
printf '%s\n' "$input"
|
|
31
31
|
exit 0
|
|
32
32
|
fi
|
|
33
33
|
|
|
@@ -39,7 +39,7 @@ cost_pct=$(echo "scale=0; $cost_usd * 100 / $COST_CAP" | bc 2>/dev/null || echo
|
|
|
39
39
|
now=$(date +%s)
|
|
40
40
|
age=$((now - ${timestamp:-0}))
|
|
41
41
|
if [ "$age" -gt 60 ]; then
|
|
42
|
-
|
|
42
|
+
printf '%s\n' "$input"
|
|
43
43
|
exit 0
|
|
44
44
|
fi
|
|
45
45
|
|
|
@@ -54,7 +54,7 @@ if [ "$cost_pct" -ge 100 ] && [ "$last_level" != "100" ]; then
|
|
|
54
54
|
echo "[Cost Cap] Session cost \$${cost_usd} has reached cap \$${COST_CAP} (${cost_pct}%)" >&2
|
|
55
55
|
echo "[Cost Cap] Consider wrapping up or increasing CLAUDE_COST_CAP" >&2
|
|
56
56
|
echo "100" > "$ADVISORY_FILE"
|
|
57
|
-
|
|
57
|
+
printf '%s\n' "$input"
|
|
58
58
|
exit 2
|
|
59
59
|
elif [ "$cost_pct" -ge 90 ] && [ "$last_level" != "90" ] && [ "$last_level" != "100" ]; then
|
|
60
60
|
echo "[Cost Cap] Session cost \$${cost_usd} at 90% of cap \$${COST_CAP}" >&2
|
|
@@ -69,5 +69,5 @@ elif [ "$cost_pct" -ge 50 ] && [ -z "$last_level" ]; then
|
|
|
69
69
|
fi
|
|
70
70
|
|
|
71
71
|
# Pass through — advisory only
|
|
72
|
-
|
|
72
|
+
printf '%s\n' "$input"
|
|
73
73
|
exit 0
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
# Advisory only — provides context hints when cwd changes
|
|
4
4
|
|
|
5
5
|
input=$(cat)
|
|
6
|
-
new_cwd=$(
|
|
6
|
+
new_cwd=$(printf '%s\n' "$input" | jq -r '.new_cwd // ""' 2>/dev/null)
|
|
7
7
|
|
|
8
8
|
if [ -z "$new_cwd" ] || [ ! -d "$new_cwd" ]; then
|
|
9
|
-
|
|
9
|
+
printf '%s\n' "$input"
|
|
10
10
|
exit 0
|
|
11
11
|
fi
|
|
12
12
|
|
|
@@ -33,4 +33,4 @@ if [ -n "$hints" ]; then
|
|
|
33
33
|
printf "%b" "$hints" >&2
|
|
34
34
|
fi
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
printf '%s\n' "$input"
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
input=$(cat)
|
|
11
11
|
if command -v jq >/dev/null 2>&1; then
|
|
12
|
-
command_text=$(
|
|
12
|
+
command_text=$(printf '%s\n' "$input" | jq -r '.tool_input.command // ""' 2>/dev/null)
|
|
13
13
|
elif command -v python3 >/dev/null 2>&1; then
|
|
14
14
|
command_text=$(INPUT_JSON="$input" python3 - <<'PY' 2>/dev/null
|
|
15
15
|
import json, os
|
|
@@ -57,4 +57,4 @@ if [ -n "$matched" ]; then
|
|
|
57
57
|
fi
|
|
58
58
|
|
|
59
59
|
# Always pass through - this hook is advisory only.
|
|
60
|
-
|
|
60
|
+
printf '%s\n' "$input"
|
|
@@ -14,7 +14,7 @@ PPID_FILE="/tmp/.claude-task-outcomes-${PPID}"
|
|
|
14
14
|
|
|
15
15
|
# Only attempt collection if outcome file exists
|
|
16
16
|
if [ ! -f "$PPID_FILE" ]; then
|
|
17
|
-
|
|
17
|
+
printf '%s\n' "$input"
|
|
18
18
|
exit 0
|
|
19
19
|
fi
|
|
20
20
|
|
|
@@ -42,5 +42,5 @@ if [ -n "$EVAL_CORE" ]; then
|
|
|
42
42
|
fi
|
|
43
43
|
|
|
44
44
|
# Always pass through input and exit 0 (advisory only)
|
|
45
|
-
|
|
45
|
+
printf '%s\n' "$input"
|
|
46
46
|
exit 0
|
|
@@ -8,16 +8,16 @@ set -euo pipefail
|
|
|
8
8
|
input=$(cat)
|
|
9
9
|
|
|
10
10
|
# Dependencies check
|
|
11
|
-
command -v jq >/dev/null 2>&1 || {
|
|
12
|
-
command -v sqlite3 >/dev/null 2>&1 || {
|
|
11
|
+
command -v jq >/dev/null 2>&1 || { printf '%s\n' "$input"; exit 0; }
|
|
12
|
+
command -v sqlite3 >/dev/null 2>&1 || { printf '%s\n' "$input"; exit 0; }
|
|
13
13
|
|
|
14
14
|
# PID scoping
|
|
15
15
|
OUTCOMES_FILE="/tmp/.claude-task-outcomes-${PPID}"
|
|
16
|
-
[ -f "$OUTCOMES_FILE" ] || {
|
|
16
|
+
[ -f "$OUTCOMES_FILE" ] || { printf '%s\n' "$input"; exit 0; }
|
|
17
17
|
|
|
18
18
|
# DB path
|
|
19
19
|
DB_PATH="${HOME}/.config/oh-my-customcode/eval-core.sqlite"
|
|
20
|
-
[ -f "$DB_PATH" ] || {
|
|
20
|
+
[ -f "$DB_PATH" ] || { printf '%s\n' "$input"; exit 0; }
|
|
21
21
|
|
|
22
22
|
# Log file for error diagnostics
|
|
23
23
|
LOG_FILE="/tmp/.claude-feedback-collector-${PPID}.log"
|
|
@@ -30,8 +30,8 @@ declare -A FAILURE_COUNTS
|
|
|
30
30
|
declare -A TOTAL_COUNTS
|
|
31
31
|
|
|
32
32
|
while IFS= read -r line; do
|
|
33
|
-
agent_type=$(
|
|
34
|
-
outcome=$(
|
|
33
|
+
agent_type=$(printf '%s\n' "$line" | jq -r '.agent_type // empty' 2>/dev/null) || continue
|
|
34
|
+
outcome=$(printf '%s\n' "$line" | jq -r '.outcome // empty' 2>/dev/null) || continue
|
|
35
35
|
[ -z "$agent_type" ] && continue
|
|
36
36
|
|
|
37
37
|
TOTAL_COUNTS[$agent_type]=$(( ${TOTAL_COUNTS[$agent_type]:-0} + 1 ))
|
|
@@ -88,5 +88,5 @@ fi
|
|
|
88
88
|
|
|
89
89
|
# CRITICAL: Always pass through input and exit 0
|
|
90
90
|
# This hook MUST NEVER block session termination
|
|
91
|
-
|
|
91
|
+
printf '%s\n' "$input"
|
|
92
92
|
exit 0
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
# Advisory warning when files are modified outside Claude Code
|
|
4
4
|
|
|
5
5
|
input=$(cat)
|
|
6
|
-
file_path=$(
|
|
7
|
-
change_type=$(
|
|
6
|
+
file_path=$(printf '%s\n' "$input" | jq -r '.file_path // ""' 2>/dev/null)
|
|
7
|
+
change_type=$(printf '%s\n' "$input" | jq -r '.change_type // "modified"' 2>/dev/null)
|
|
8
8
|
|
|
9
9
|
if [ -z "$file_path" ]; then
|
|
10
|
-
|
|
10
|
+
printf '%s\n' "$input"
|
|
11
11
|
exit 0
|
|
12
12
|
fi
|
|
13
13
|
|
|
@@ -23,4 +23,4 @@ case "$file_path" in
|
|
|
23
23
|
;;
|
|
24
24
|
esac
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
printf '%s\n' "$input"
|
|
@@ -14,8 +14,8 @@ command -v jq >/dev/null 2>&1 || exit 0
|
|
|
14
14
|
|
|
15
15
|
input=$(cat)
|
|
16
16
|
|
|
17
|
-
agent_type=$(
|
|
18
|
-
prompt=$(
|
|
17
|
+
agent_type=$(printf '%s\n' "$input" | jq -r '.tool_input.subagent_type // ""')
|
|
18
|
+
prompt=$(printf '%s\n' "$input" | jq -r '.tool_input.prompt // ""')
|
|
19
19
|
|
|
20
20
|
# R010 violation tracking file (PPID-scoped for session persistence)
|
|
21
21
|
VIOLATION_FILE="/tmp/.claude-r010-violations-${PPID}"
|
|
@@ -54,4 +54,4 @@ if [ "$agent_type" != "mgr-gitnerd" ]; then
|
|
|
54
54
|
fi
|
|
55
55
|
|
|
56
56
|
# Always pass through - this hook is advisory only
|
|
57
|
-
|
|
57
|
+
printf '%s\n' "$input"
|