𪀠hookã®exit codeããŒãã«æœ°ãã â ãµãã·ã§ã«å€æ®µã®æ²é»ãã°
24æéãããã·ã¥ããŒãã¯ãã¹ãŠç·ã§ãããlaunchdã®ãžã§ãã¯å
šä»¶ exit 0ããã°ã«ã¯ (exit 0) ãæŽç¶ãšäžŠãã§ããŸãããã§ãå®éã«ã¯XïŒæ§TwitterïŒãžã®DMè¿ä¿¡ãäžžäžæ¥ãŒãä»¶ãYouTrustãåæ§ã§ããããšã©ãŒã¯èµ·ããŠããŸããããã ãçµäºã³ãŒããåŒã³åºãå
ã«å±ããŠããªãã£ãã ãã§ãã
倧åŠçã®ããã¯ããªãŒã©ã³ã¹æãæã¡ã§æ60äžãŸã§ç©ã¿äžããã®ã«ãäŒç€Ÿéœåã®è§£éã§äžåºŠãŒãã«æ»ããŸãããããããå幎ãããŠClaude Codeã®èªåŸç°å¢ãæ§ç¯ããŠãä»ã¯æå120äžã®ã©ã€ã³ã«ä¹ã£ãŠããŸãããã®èšäºã¯ãã®ç°å¢ãæ¯ããŠããhookã®é ç·ââæ£ç¢ºã«ã¯ãé ç·ããã€ãããäœãåºãã£ãŠããªãã£ããšãã®è©±ã§ãã
ãªããã®ä»çµã¿ãå¹ãã®ã
Claude Codeã«ã¯ PreToolUse ãš Stop ãšãã2çš®é¡ã®ããã¯ãã€ã³ãããããŸããPreToolUseã¯ClaudeãããŒã«ãåŒã³åºãçŽåã«å²ã蟌ã¿ãStopã¯å¿çãçµäºããããšããçŽåã«èµ°ããŸããããã¯ã¹ã¯ãªããã exit 1 ãè¿ããšãClaudeã¯ãã®ããŒã«ã³ãŒã«ãStopåäœããããã¯ããŸãââ仿§äžã¯ã
ãã®ä»çµã¿ãç¥ã£ããšããèªååç°å¢ã®ã¬ãŒãã¬ãŒã«ãšããŠå³åº§ã«äœ¿ããããšæããŸããããç£æ»ãæžãŸããŠããªãå®è£ ãå®äºæ±ãã«ãããªãããç§å¿å€ãã³ãããã«çŽã蟌ã¿ãããªãæ¢ããããæå®ã®ã¹ã¯ãªããã倱æãããActionãåãæ¶ãããããããã³ãŒãã§æžããŠãClaudeã®è¡åãå€åŽããå¶åŸ¡ã§ããã
å®éãç°å¢ãåããŠãã身ãšããŠççŽã«èšããšã171æ¬ã®launchdãžã§ããšè€æ°ã®Claude Codeã»ãã·ã§ã³ãåæã«åããŠããç¶æ³ã§ãããã¯ããªããã°æ¯æ¥äœããå£ããŸããèšå®ãã¹ã»ç°å¢å·®ç°ã»ã¢ãã«ã®æ°ãŸãããã©ããããã¯ã§äžæ¬é£ãã§ãããã ãããããããã¯ããå¹ããŠãããµãããããŠããã ãã§å®éã«ã¯äœãæ¢ããŠããªãç¶æ ã¯ãã¬ãŒãã¬ãŒã«ã®ãªãåŽãšåãã§ãã
èªè ãçŽé¢ããã·ããªãª
Claude Code䜿ããªããæ¬¡ã®ããããã§åŒã£ãããå¯èœæ§ãé«ãã§ãã
ãã¿ãŒã³AïŒã·ã§ã«ã¹ã¯ãªããã§ããã¯ãæžããŠããã ã¹ã¯ãªããã exit 1 ãè¿ããŠããClaudeãæ¢ãŸããªãããã°ãèŠããšçµäºã³ãŒãã 0 ã«ãªã£ãŠãããã¹ã¯ãªããèªäœã¯æ£ããæžããã¯ããªã®ã«ã
ãã¿ãŒã³BïŒããã¯ãJSã©ãããŒçµç±ã§åŒãã§ããã JSã©ãããŒã child_process.exec() ã $() ã³ãã³ã眮æã䜿ã£ãŠå
åŽã®ã·ã§ã«ã¹ã¯ãªãããåŒã¶æ§é ã«ããŠãããå
åŽã®ã¹ã¯ãªããã exit 1 ãè¿ããŠããå€åŽã®JSããã»ã¹ã«ã¯ 0 ãšããŠå±ãã
ãã¿ãŒã³CïŒãã€ãã©ã€ã³ã®äžã§ã¹ã¯ãªãããåŒãã§ããã cat input.json | ./hook-script.sh ã®ããã«æšæºå
¥åããã€ãã§æž¡ããŠãããset -o pipefail ãªãã§ã¯ããã€ãå³èŸºã®ã¹ã¯ãªããã®çµäºã³ãŒãããåŒã³åºãå
ã«å±ããªãã
ãããããããã¯ãæžããããåããŠãããããã°ãåºãŠãããââããã§ãã¬ãŒãã¯æ©èœããŠããŸãããèŠèŠçã«ç·ãªã®ã«ãå®éã«ã¯äœãå®ãããŠããªãç¶æ ã§ãããããæ²é»ãã°ã®æ¬è³ªã§ãã
ã倱æãèµ·ããªãã£ããã§ã¯ãªãã倱æã³ãŒããçããªãã£ãã
ã€ã³ã·ãã³ãã®æ¥ãDMã·ã¹ãã ã®ãã°ã¯å
šè¡ (exit 0) ã§ãããã§ãåé¡ã¯ãã®ãã°ã®è¡ã«ãã£ããå®éã«èµ°ã£ãŠããã®ã¯ãã®ã³ãŒãã§ãã
node "$SCRIPT" "$@"
echo "[$(date '+%F %T')] $LANE done (exit $?)"
echo ã®åŒæ°ã¯å·Šããè©äŸ¡ãããŸãã$(date '+%F %T') ã¯ãµãã·ã§ã«ãèµ·åããŠââãããŠæåããŠââåž°ã£ãŠããŸãããã®ç¬éã$? 㯠0 ã«äžæžããããŸãã$? ãèªãŸããã®ã¯ãã®ããšã§ããã€ãŸããã®è¡ã¯ãçŽåã® node ã exit 3 ã§èœã¡ããã exit 4 ã§èœã¡ããããæ§æäžãã£ããã« (exit 0) ãšããåºåã§ããŸããã
å®èšŒãšããŠãä¿®æ£å㯠exit 4 ã 0 ãšè¡šç€ºãããä¿®æ£åŸã¯ 4 ãšåºãããšãåçŸãã¹ãã§ç¢ºèªããŠããŸãã
æãããã®ã¯é¡åããããšã§ãããã®è¡ãå
¥ã£ãŠããéããéå»ã®ãã°ã«äžŠãã (exit 0) ã¯1ä»¶ã蚌æ ã«ãªããŸããããå
é±ãå
æãç·ã ã£ããã¯ãç·ãå°åããã ãã®ã³ãŒããæ¯åèžãã§ããã ãã§ãã
ãã®çœ 㯠~/dev é
äžãš ~/.claude/scripts ã®328æ¬ã®ã·ã§ã«ã¹ã¯ãªãããèµ°æ»ãããšãããåèš3ä»¶èŠã€ãããŸãããClaude Codeã®ããã¯åšèŸºã«1ä»¶ãnoteã®ææç¹å
žZIPæ·»ä»ã¹ã¯ãªããã«1ä»¶ãdotfilesã®ã¹ãããã·ã§ããã¹ã¯ãªããã«1ä»¶ãã©ããããã°ã¯åºãŠãããã§ãçµäºã³ãŒãã¯æ»ãã§ãããç¶æ
ã§ããã
å šäœã®æµã
ãŸããClaude Codeã®Stop/PreToolUseããã¯ãã©ãããçµè·¯ã§ã·ã§ã«ã¹ã¯ãªãããåŒã¶ãã確èªããŸãã
åŒã³åºããã§ãŒã³ã®å šäœå
Claude CodeïŒæ¬äœããã»ã¹ïŒ
â
â hook event (JSON payload ã stdin ã«æž¡ã)
âŒ
JS hook dispatcherïŒsettings.json ã§æå®ïŒ
â
â child_process.spawn() ãŸã㯠exec()
âŒ
~/.claude/scripts/hooks/run-with-flags-shell.sh
â
â stdin â ãã€ãçµç±ã§æž¡ã
â HOOK_ID / REL_SCRIPT_PATH / PROFILES_CSV ãåŒæ°ã§åãåã
âŒ
check-hook-enabled.jsïŒãã®hookãæå¹ã確èªïŒ
â
â enabled ãªãã°
âŒ
$SCRIPT_PATHïŒå®éã®ããã¯ããžãã¯ïŒ
â
â exit 0 / exit 1
âŒ
run-with-flags-shell.shïŒçµäºã³ãŒããè¿ãïŒ
â
âŒ
JS dispatcherïŒçµäºã³ãŒããåãåã â Claudeæ¬äœãžïŒ
â
âŒ
Claude CodeïŒexit 1 ãªãåäœããããã¯ïŒ
ãã®å³ã®åç¢å°ããçµäºã³ãŒããæ£ããæž¡ããŠããããããã€ã³ãã§ãã1æ¬ã§ãéåããããæ«ç«¯ã® exit 1 ã¯Claudeã«å±ããŸããã
run-with-flags-shell.sh ã®å®ã³ãŒã
å®éã®ã©ãããŒã¹ã¯ãªããã¯æ¬¡ã®ãšããã§ãïŒ~/.claude/scripts/hooks/run-with-flags-shell.shïŒã
#!/usr/bin/env bash
set -euo pipefail
HOOK_ID="${1:-}"
REL_SCRIPT_PATH="${2:-}"
PROFILES_CSV="${3:-standard,strict}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "${SCRIPT_DIR}/../.." && pwd)}"
# Preserve stdin for passthrough or script execution
INPUT="$(cat)"
if [[ -z "$HOOK_ID" || -z "$REL_SCRIPT_PATH" ]]; then
printf '%s' "$INPUT"
exit 0
fi
# Ask Node helper if this hook is enabled
ENABLED="$(node "${PLUGIN_ROOT}/scripts/hooks/check-hook-enabled.js" "$HOOK_ID" "$PROFILES_CSV" 2>/dev/null || echo yes)"
if [[ "$ENABLED" != "yes" ]]; then
printf '%s' "$INPUT"
exit 0
fi
SCRIPT_PATH="${PLUGIN_ROOT}/${REL_SCRIPT_PATH}"
if [[ ! -f "$SCRIPT_PATH" ]]; then
echo "[Hook] Script not found for ${HOOK_ID}: ${SCRIPT_PATH}" >&2
printf '%s' "$INPUT"
exit 0
fi
# Extract phase prefix from hook ID (e.g., "pre:observe" -> "pre", "post:observe" -> "post")
HOOK_PHASE="${HOOK_ID%%:*}"
printf '%s' "$INPUT" | "$SCRIPT_PATH" "$HOOK_PHASE"
set -euo pipefail ããã¡ã€ã«å
é ã«ãããŸããããã¯ãã³ãã³ãã倱æãããå³çµäºã»æªå®çŸ©å€æ°ã¯ãšã©ãŒã»ãã€ãå
ã®å€±æãæŸãããšããæãå
ãèšå®ã§ããæçµè¡ã® printf '%s' "$INPUT" | "$SCRIPT_PATH" "$HOOK_PHASE" ã¯ãã€ãã䜿ã£ãŠããŸãããpipefail ãããããå³èŸºã® $SCRIPT_PATH ã exit 1 ãè¿ãã° run-with-flags-shell.sh èªäœã exit 1 ã§çµãããŸãââãã®ã¹ã¯ãªããåäœã®äžã§ã¯ã
åé¡ã¯ããã®ã¹ã¯ãªããã®å€åŽã«ãããŸãã
ãã§ãŒã³ã®äžã§å®éã«èµ·ããããš
泚ç®ç¹â ïŒ19è¡ç®ã® check-hook-enabled.js åŒã³åºã
ENABLED="$(node "${PLUGIN_ROOT}/scripts/hooks/check-hook-enabled.js" "$HOOK_ID" "$PROFILES_CSV" 2>/dev/null || echo yes)"
$() ã®äžã® node ãäœããã®ãšã©ãŒã§èœã¡ãå Žåã|| echo yes ãçºåã㊠ENABLED 㯠"yes" ã«ãªããŸããã€ãŸãhook確èªã¹ã¯ãªããèªäœãå£ããŠããŠããããã¯ã¯ãæå¹ããšããŠå®è¡ãã¹ã«é²ã¿ãŸããããã¯ãã©ãŒã«ããã¯èšèšãšããŠæå³çã§ãããããã¯ç¢ºèªããžãã¯ã®ãšã©ãŒããµã€ã¬ã³ãã«é£²ã¿èŸŒãŸããæ§é ã§ãã
泚ç®ç¹â¡ïŒæçµè¡ã®ãã€ã
printf '%s' "$INPUT" | "$SCRIPT_PATH" "$HOOK_PHASE"
pipefail ãããã®ã§ $SCRIPT_PATH ã® exit 1 ã¯ã¡ãããšãã®ã¹ã¯ãªããã®çµäºã³ãŒãã«äŒæããŸããããã JSãã£ã¹ãããã£ãŒããã®ã¹ã¯ãªãããã©ãåŒã¶ãã«ãã£ãŠããã®ã³ãŒããClaudeã«å±ããã©ãããå€ãããŸãã
JSã child_process.exec() ã䜿ã£ãŠããå Žåãã³ãŒã«ããã¯ã®ç¬¬1åŒæ°ïŒerrorïŒãnullãã©ããã§æåŠãå€å®ããŸããexec ã¯å
éšçã«ã·ã§ã«ãæããããã·ã§ã«ã®çµäºã³ãŒãã error.code ãšããŠå±ããŸãââãã ã exec ã®ãªãã·ã§ã³ã§ shell: true ã«ãªã£ãŠãããšãã·ã§ã«èªäœã exit 1 ãåŠçããŠèŠªããã»ã¹ã«ã¯äŒãããªãã±ãŒã¹ããããŸãã
child_process.spawn() ã䜿ã£ãŠããå Žå㯠close ã€ãã³ãã® code åŒæ°ã§çµäºã³ãŒããåããŸããããã¯æŠãæ£ç¢ºã§ãããã¹ããŒã³ãããããã»ã¹ã SIGTERM ã SIGKILL ã§çµãã£ãå Žåãcode 㯠null ã«ãªããŸãã
ããã²ãšã€ãJSãã $(run-with-flags-shell.sh ...) ã®ããã«ã³ãã³ã眮æã§åŒãã§ããå Žåã¯ââå
ã»ã©èª¬æãããšããââ$? ã確å®ã«ç Žå£ãããŸãã
å®éã®ã€ã³ã·ãã³ãæ°å€
2026幎8æ29æ¥ã®ã€ã³ã·ãã³ãã§ã¯æ¬¡ã®ç¶æ³ã確èªãããŸããã
| åªäœ | èµ·ååæ° | å®éã®è¿ä¿¡æ° | ã¢ã©ãŒãçºå ± |
|---|---|---|---|
| XïŒæ§TwitterïŒ | 6åïŒå šä»¶ABORTïŒ | 0é | 3åç®ä»¥éã¯åºãŠããïŒ14:33 / 16:15 / 18:15 / 20:15ïŒ |
| YouTrust | 6åïŒå šä»¶èµ·å倱æïŒ | 0é | 1ä»¶ãåºãŠããªã |
XåŽã¯çµäºã³ãŒããäžéšçµè·¯ãéã£ãŠç£èŠç³»ãŸã§å±ããŠããããã3åç®ä»¥éã¯Discordã® #01_alerts ã«éç¥ãåºãŠããŸãããYouTruståŽã¯ã©ã€ãã©ãªå±€ã® process.exit(3) ãåŒã³åºãå
ã® catch ãããã¯ããã€ãã¹ãããããread_failures ã«ãŠã³ã¿ãŒãå ç®ããããDiscordã«ã¯1ä»¶ãéç¥ãåºãŸããã§ããã
åãæ¥ã»åãçå ïŒChromeèµ·å倱æïŒã»åãã¢ãŒããã¯ãã£ææ³ã§ãçæ¹ã¯é³Žã£ãŠçæ¹ã¯å®å šç¡é³ãå·®ã¯ã©ã€ãã©ãªã®1è¡ã ãã§ãããã®1è¡ãã24æéåã®å¶æ¥DMãæ²é»ãããŠããŸããã
ã³ãŒãã¬ãã«ã§äœãèµ·ããŠããã
ããã¯ã®JSã©ãããŒã $() ã䜿ã£ãŠã·ã§ã«ã¹ã¯ãªãããåŒã¶æ§é ããæå°éã®ãµã³ãã«ã§ç€ºããŸãã
// â $() çµç±ã§ã¯ exit code ãæœ°ãã
const { execSync } = require('child_process');
function runHook(scriptPath, input) {
try {
// execSync ã¯ããã©ã«ãã§ throws on non-zero exit
// ãããå
éšã§ $() ãéãããšè©±ãå€ãã
const result = execSync(`echo '${input}' | ${scriptPath}`, {
encoding: 'utf8',
shell: true, // â ãããåé¡ã®æž©åºã«ãªãããã
});
return { success: true, output: result };
} catch (e) {
// e.status ã null ã«ãªãã±ãŒã¹ããã
return { success: false, code: e.status };
}
}
shell: true ãªãã·ã§ã³ã¯ã³ãã³ãæååã /bin/sh -c "..." ã«æž¡ããŸãããã®ã·ã§ã«ã©ãããŒã exit 1 ããã®ãŸãŸããã»ã¹ã®çµäºã³ãŒããšããŠäŒãããã©ããã¯ãã·ã§ã«ã®å®è£
ãšåŒæ°ã®çµã¿ç«ãŠæ¹ã«äŸåããŸããç¹ã« echo '...' | script.sh ã®ãããªãã€ãã shell: true ã§æž¡ããå Žåãpipefail ã¯ãã®ã·ã§ã«ã»ãã·ã§ã³ã«ã¯åŒãç¶ãããªãããã巊蟺ã®å€±æã¯æ¡ã朰ãããŸãã
äžæ¹ãrun-with-flags-shell.sh èªèº«ãæçµè¡ã§äœ¿ã£ãŠãããã€ãââ
printf '%s' "$INPUT" | "$SCRIPT_PATH" "$HOOK_PHASE"
ââã¯ã¹ã¯ãªããå
é ã® set -euo pipefail ã®æ¯é
äžã«ããããã$SCRIPT_PATH ã® exit 1 ã¯ã¹ã¯ãªããã®çµäºã³ãŒããšããŠæ£ããäžãããŸãããã®ã¹ã¯ãªããåäœã¯æ£ãããåé¡ã¯ãã®äžã®åŒã³åºãå±€ã«ãããŸãã
328æ¬ã®èµ°æ»ã§èŠã€ãã£ã3ä»¶ã®çœ ã¯ããã¹ãŠãã¹ã¯ãªããå
ã® echo è¡ã« $(date) ãš $? ãæ··åšããŠããããã¿ãŒã³ã§ãããæ€åºã¯ãšãªã¯ãã®ãŸãŸäœ¿ããŸãã
grep -rn 'exit \$?' --include='*.sh' ~/dev ~/.claude/scripts | grep '\$('
ãã®ã¯ãšãªã¯ exit $? ãå«ãè¡ã®ãã¡ãåäžè¡ã« $( ãåºçŸãããã®ãæŸããŸãã|| rc=$? ã®ãããªä»£å
¥ãã¿ãŒã³ïŒx="$(cmd)" || rc=$?ïŒã¯æ£ããæžãæ¹ãªã®ã§ããã®å€å¥ã ãæ©æ¢°çã«ã¯ã§ããŸããââç®èŠãå¿
èŠã§ãã
å®è£ ã®è©³çް
ååã§ã¯ããªãçµäºã³ãŒããå±ããªãããã®æ§é ã远ããŸãããããããã¯ãã©ãæžãçŽããšå±ãããã«ãªãããããå®ã³ãŒããåŒããªããå ·äœçã«èŠãŠãããŸããä¿®æ£ãã¿ãŒã³ã¯3ã€ãããŸãããããã2è¡ä»¥å ã®å€æŽã§ãããããã«ããŒããçµè·¯ãéããŸãã
ãªã set -euo pipefail ã ãã§ã¯ãå€åŽããæãããªãã
~/.claude/scripts/hooks/run-with-flags-shell.sh ã®å
é ã¯æ¬¡ã®ãšããã§ãã
#!/usr/bin/env bash
set -euo pipefail
ãã®è¡ã¯ããã®ã¹ã¯ãªããã®å®è¡ã³ã³ããã¹ãå
ã§ã¯ pipefail ãæå¹ãã§ããããšãä¿èšŒããŸããå®éãæçµè¡
printf '%s' "$INPUT" | "$SCRIPT_PATH" "$HOOK_PHASE"
㯠pipefail ã®æ¯é
äžã«ããããã$SCRIPT_PATH ã exit 1 ãè¿ãã° run-with-flags-shell.sh èªäœã exit 1 ã§çµãããŸããããã¯æ£ããã
åé¡ã¯ãJSãã£ã¹ãããã£ãŒããã®ã·ã§ã«ã¹ã¯ãªãããã©ãèµ·åããããã§ããJSã child_process.exec() ã« shell: true ãæž¡ããŠããå Žåãã³ãã³ãæååã¯å
éšçã« /bin/sh -c "..." ã§å
ãŸããŸãããã® /bin/sh ã»ãã·ã§ã³ã«ã¯ pipefail ãåŒãç¶ãããŸãããJSããèŠãããã»ã¹ããªãŒã¯ã/bin/sh â run-with-flags-shell.shãã§ã¯ãªãããã·ã§ã«ã©ãã㌠â ãã®åããã»ã¹ãšã㊠run-with-flags-shell.shãã«ãªããŸããã·ã§ã«ã©ãããŒèªèº«ã®çµäºã³ãŒãã¯éåžž 0 ã§ãã
ããã²ãšã€ãJSã execSync ã§ã³ãã³ã眮æçã«çµææååãåãåºããŠããå Žåââ
const out = execSync(`cat payload.json | ${hookScript}`, { shell: true });
ââ巊蟺㮠cat payload.json ãæåããéããå³èŸºã® hookScript ãäœãè¿ããŠã execSync ã®ãšã©ãŒå€å®ã«ã¯åœ±é¿ããŸãããshell: true + ãã€ã + pipefail ãªãã®çµã¿åããã¯ãå³èŸºã®çµäºã³ãŒããéãã«æšãŠãŸãã
ãã¿ãŒã³1ïŒ$? ã $(...) ããå
ã«éé¿ãã
æã軜ãä¿®æ£ã§ãã察象ã¯ããã°è¡ã« $(date) ãš $? ãæ··åšããŠããã±ãŒã¹ãå
šè¬ã«äœ¿ããŸãã
# â BeforeïŒ$? ã $(date) ã§äžæžãããã
node "$SCRIPT" "$@"
echo "[$(date '+%F %T')] $LANE done (exit $?)"
# â
AfterïŒSTATUS ã«éé¿ããŠãã $(date) ãå±éãã
node "$SCRIPT" "$@"
STATUS=$?
echo "[$(date '+%F %T')] $LANE done (exit $STATUS)"
STATUS=$? ã¯åãªã倿°ä»£å
¥ãªã®ã§ããµãã·ã§ã«ãèµ·åããŸããã$? ã¯æ¬¡ã®è¡ã® $(date) ã«å£ãããåã«ç¢ºä¿ãããŸããããã ãã§ããã°ãå°åããã³ãŒããšå®éã®çµäºã³ãŒãã®ä¹é¢ãã¯æ¶ããŸãã
ãã ãæ³šæç¹ããããŸãã代å
¥åŒã® x="$(cmd)" ãšãã圢㯠代å
¥å
šäœã®çµäºã¹ããŒã¿ã¹ã $(cmd) ã®ããã«ãªããããããã¯æ£ããæžãæ¹ã§ãã
# â
ããã¯æ£ãããx ã®ä»£å
¥ã¹ããŒã¿ã¹ã¯ node ã®ã¹ããŒã¿ã¹ãšåã
x="$(node "$SCRIPT" "$@")"
STATUS=$?
äžæ¹ã$() ãå«ã echo è¡ã® $? ã¯ç¢ºå®ã«ãŒãã«ãªããŸãã2ã€ã®åœ¢ã®å·®ã¯ãgrep ã§æ©æ¢°çã«ã¯åºå¥ã§ããŸããââæ£èŠè¡šçŸã§ãããããããšç®èŠã1ã¹ãããèŠããŸãã
æ€åºã¯ãšãªïŒååã«ç€ºãããã®ãšåäžïŒïŒ
grep -rn 'exit \$?' --include='*.sh' ~/dev ~/.claude/scripts | grep '\$('
ãã®ã¯ãšãªãè¿ãè¡ã®ãã¡ãx="$(...)" 圢ã¯é€å€ããŠãã ãããæ®ãã¯å
šéšä¿®æ£å¯Ÿè±¡ã§ãã
ãã¿ãŒã³2ïŒPIPESTATUS ã§è€æ°ã³ãã³ãã®ã³ãŒããå
šéšåãåã
ãã€ããæžãæããããªãå Žåã«äœ¿ããŸããPIPESTATUS 㯠bash åºæã®é
åã§ãçŽåã®ãã€ãã©ã€ã³ã®åã³ãã³ãã®çµäºã³ãŒããå·Šããé ã«ä¿æããŸãã
printf '%s' "$INPUT" | "$SCRIPT_PATH" "$HOOK_PHASE"
PIPE_STATUS=("${PIPESTATUS[@]}")
# PIPE_STATUS[0] = printf ã®çµäºã³ãŒã
# PIPE_STATUS[1] = $SCRIPT_PATH ã®çµäºã³ãŒã
if [[ "${PIPE_STATUS[1]}" -ne 0 ]]; then
exit "${PIPE_STATUS[1]}"
fi
run-with-flags-shell.sh ã¯å
é ã« set -euo pipefail ãããããããããæžãè¶³ãå¿
èŠã¯çŸæç¹ã§ãããŸããââpipefail ãããã°å³èŸºã®å€±æã§ã¹ã¯ãªããèªäœãèœã¡ãŸããPIPESTATUS ãæç€ºããã®ã¯ãpipefail ãå€ããªãäºæ
ãããå Žåãããã©ã¡ãã®ã³ãã³ããèœã¡ãããèšé²ãã°ã«æ®ãããå Žåãã§ããlaunchd ã®ãžã§ããã°ã«åªäœåãšçµäºã³ãŒãã®å¯Ÿãæ®ãèšèšãªããPIPESTATUS[1] ãçŽæ¥ãã°ã«æžãã»ããåŸããã®è¿œè·¡ã楜ã§ãã
ãã¿ãŒã³3ïŒJS ãã£ã¹ãããã£ãŒãçŽåŒã³ã«æžãçŽã
æãæ ¹æ¬çãªä¿®æ£ã§ããshell: true + exec ã spawn ã«çœ®ãæããã·ã§ã«ã©ãããŒãçµç±ããªãããã«ããŸãã
// â BeforeïŒshell: true ã®ãã $() å
ã® pipefail ãæ»ã¬
const { execSync } = require('child_process');
const out = execSync(`echo '${payload}' | ${hookScript}`, { shell: true });
// â
AfterïŒspawn ã§çŽæ¥åŒã¶ãçµäºã³ãŒã㯠close ã€ãã³ãã® code ã§åãã
const { spawn } = require('child_process');
function runHook(hookScript, payload) {
return new Promise((resolve, reject) => {
const child = spawn(hookScript, [], { stdio: ['pipe', 'pipe', 'inherit'] });
child.stdin.write(payload);
child.stdin.end();
child.on('close', (code) => {
if (code !== 0) {
reject(new Error(`hook exited with ${code}`));
} else {
resolve();
}
});
});
}
spawn 㯠shell: true ãªãã§äœ¿ãã°ãã³ãã³ãããã®ãŸãŸ execve(2) ã§èµ·åããŸããã·ã§ã«ã©ãããŒãå
¥ããªããããrun-with-flags-shell.sh å
ã® set -euo pipefail ã¯ãã®ãŸãŸæå¹ã«ãªããŸããclose ã€ãã³ãã® code åŒæ°ã¯ nullïŒã·ã°ãã«çµäºïŒãæŽæ°ïŒéåžžçµäºïŒã®ããããã§ããnull ã®å Žå㯠signal åŒæ°ã§äœãèµ·ãããã確èªããŸãã
æå° exit 1 åçŸã§ã¬ãŒããåºããã確ããã
ãä¿®æ£ãããã ãã§ã¯çµãããŸãããå®éã«Claudeã®åäœããããã¯ãããããæå°ã®åçŸã±ãŒã¹ã§æ€èšŒããŸããæé ã¯3ã¹ãããã§ãã
ã¹ããã1ïŒåžžã« exit 1 ãè¿ããããŒããã¯ãäœãã
#!/usr/bin/env bash
# /tmp/test-hook.sh
exit 1
chmod +x /tmp/test-hook.sh
ã¹ããã2ïŒsettings.json ã§ãã®ããã¯ãStopããã¯ã«æå®ããã
{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "/tmp/test-hook.sh"
}
]
}
]
}
}
ã¹ããã3ïŒClaude CodeãéããŠãäœããçããããŠã¿ãã
Claudeãå¿çãçµäºããããšããç¬éã«Stopããã¯ãèµ°ããŸãã/tmp/test-hook.sh ã exit 1 ãè¿ãã°ãClaudeã¯ãããã¯ããããã¯ããŸãããæšã®ã¡ãã»ãŒãžãåºããŠåã«ãŒãããŸãããããåºãã°é
ç·ã¯çããŠããŸãã
JSãã£ã¹ãããã£ãŒçµç±ã§åŒãã§ããå Žåããã®ãã¹ããééããŠãå®éã®ããã¯ã¹ã¯ãªããã spawn çµç±ãã©ããã¯å¥åé¡ã§ããç¢ºèªæ¹æ³ã¯ ps aux | grep hook ã§Claudeãäœãèµ·åããŠããããèŠãããšããŸã㯠strace / dtruss ã§ execve ç³»ã®ã·ã¹ãã ã³ãŒã«ã远ãããšã§ããmacOS ã§ã¯ dtruss -p <PID> ã§ããã»ã¹ãèµ·åããåããã»ã¹ã®ã·ã¹ãã ã³ãŒã«ã確èªã§ããŸãã
ç§ãè©°ãŸã£ã話
ããããã¯å®éã«è©°ãŸã£ãé çªã§æžããŸããçç¶ã»åå ã»çŽãæ¹ã®3ç¹ã»ããã§3ä»¶ãã©ãããããã¯ãæžãããåããŠããããã°ãåºãŠãããç¶æ ã§è©°ãŸã£ã話ã§ãã
1ä»¶ç®ïŒ28æéãã°ãå šéšç·ãå®éã®è¿ä¿¡ã¯ãŒãä»¶
çç¶ã 2026幎8æ29æ¥ããXïŒæ§TwitterïŒã®DMè¿ä¿¡ãæè¿é
ããªãïŒãã®äžèšããæãå§ããŸãããlaunchdã®ãžã§ãäžèЧã確èªãããšå
šä»¶ exit 0ããã°ãã¡ã€ã«ã«ã¯
[2026-08-29 06:15:32] inbox-agent done (exit 0)
[2026-08-29 08:15:17] inbox-agent done (exit 0)
[2026-08-29 10:15:41] inbox-agent done (exit 0)
ãæŽç¶ãšäžŠãã§ããŸãããç·ã§ãããã§ãå®éã®è¿ä¿¡ä»¶æ°ã¯ç¢ºèªã§ããXåŽã®ã€ã³ã¿ãŒãã§ãŒã¹ã§èª¿ã¹ããšãäžžäžæ¥ãŒãä»¶ã§ããã
åå ã inbox-agent/run-medium.sh ã®äžã«æ¬¡ã®è¡ããããŸããã
node "$SCRIPT" "$@"
echo "[$(date '+%F %T')] $LANE done (exit $?)"
ããã§ããnode "$SCRIPT" ããšã©ãŒã§èœã¡ãŠããŸããã$? ã«ã¯ node ã®çµäºã³ãŒããå
¥ã£ãŠããŸãââãã®è¡ãè©äŸ¡ãããçŽåãŸã§ã¯ãecho ã®åŒæ°ãå±éãããšããbash ã¯å·Šããå³ã«è©äŸ¡ããŸãã$(date '+%F %T') ã¯ãµãã·ã§ã«ãèµ·åããŠãæ¥ææååãè¿ããŠãæåããŸãããã®ç¬éã$? 㯠0 ã«æžãæãããŸããæ¬¡ã« $? ãèªãŸããŸããã ããäœãèµ·ããŠããã°ã¯ (exit 0) ã«ãªããŸãã
çŽãæ¹ã
node "$SCRIPT" "$@"
STATUS=$?
echo "[$(date '+%F %T')] $LANE done (exit $STATUS)"
1è¡å¢ãã㊠STATUS ã«éé¿ããã ãã§ãããã®ä¿®æ£åŸãåã Chrome èµ·å倱æãåçŸããããš (exit 3) ãšå°åãããŸãããlaunchd ã exit 3 ãåãåããDiscordã®Alertãã£ã³ãã«ã«éç¥ãå±ããŸããã
æãããã£ãããšã ãã®è¡ãå ¥ã£ãŠããæéã®ãã°ã¯ãã¹ãŠç¡å¹ã§ãããå é±ãå æãç·ã ã£ããã¯èšŒæ ã«ãªããŸããããå é±ãå æããç·ãšå°åããã ãã®ã³ãŒããå®è¡ãç¶ããŠããããšããã ãã§ãã
2ä»¶ç®ïŒnoteææç¹å žZIPã®æ·»ä»å€±æã3é±éæ°ã¥ãããªãã£ã
çç¶ã 1ä»¶ç®ã®ä¿®æ£åŸãããããŸã§æ¥ããªãä»ã®ã¹ã¯ãªãããåãçœ ãèžãã§ããå¯èœæ§ãããããšæãã328æ¬ã®ã·ã§ã«ã¹ã¯ãªãããèµ°æ»ããŸããã
grep -rn 'exit \$?' --include='*.sh' ~/dev ~/.claude/scripts | grep '\$('
3ä»¶ãããããŸãããinbox-agent/run-medium.shïŒä»åã®äž»ç¯ïŒã~/.claude/scripts/dotfiles-snapshot.shïŒcommit倱ææã®çµäºã³ãŒãïŒããã㊠note-autolike/scripts/retry-attach-kit.sh ã§ãã
retry-attach-kit.sh ã確èªãããšãnoteã®ææç¹å
žZIPãæçš¿ã«æ·»ä»ãããªãã©ã€ã¹ã¯ãªããã§ãããæ·»ä»APIã503ãè¿ãããšããã¹ã¯ãªãã㯠exit 1 ãè¿ãããã«æžãããŠããŸãããããã echo è¡ã«åãçœ ãå
¥ã£ãŠãããããlaunchdã«ã¯ exit 0 ãšããŠèšé²ãããŠããŸããã
æænoteãè³Œå ¥ãã人ãç¹å žZIPãããŠã³ããŒãã§ããªãç¶æ ããã©ã®ãããã®æéç¶ããŠãããââãã°ãé¡ã£ãŠãå šéšç·ãªã®ã§å€å¥ã§ããŸãããæ·»ä»ã¹ã¯ãªãããæåŸã«æåããå®éã®æ¥ä»ããnoteã®ç®¡çç»é¢ã®æ·»ä»ãã¡ã€ã«æŽæ°æ¥ãšç §åãããããããŸããã§ãããçµæãšããŠå°ãªããšã3é±éã¯å€±æç¶æ ã®ãŸãŸç·ãã°ãåºãç¶ããŠããããšãããããŸããã
åå ãšçŽãæ¹ã åããã¿ãŒã³ã§ãã
# â Before
python3 attach_kit.py "$POST_ID" "$ZIP_PATH"
echo "[$(date '+%F %T')] attach done (exit $?)"
# â
After
python3 attach_kit.py "$POST_ID" "$ZIP_PATH"
STATUS=$?
echo "[$(date '+%F %T')] attach done (exit $STATUS)"
ä¿®æ£åŸã« STATUS ã 1 以äžã§çµãã£ãå Žåãã¢ã©ãŒããDiscordã«äžããããã«ããŸãããæænoteã®è³Œå
¥è
ã«åœ±é¿ãåºã倱æã¯ãç¿æãŸã§æ°ã¥ããªãã®ã¯èš±å®¹ã§ããŸããã
åŠã³ãšããŠæ®ã£ãããšã 1ä»¶èŠã€ããæç¹ã§å³åº§ã«æšªå±éããªããã°ããã®æ¡ä»¶ã¯ä»ããµã€ã¬ã³ãã«å€±æãç¶ããŠããŸãããåãã³ãŒããã¿ãŒã³ã¯å¿ ãè€æ°ç®æã«ååšããŸããã1ä»¶ä¿®æ£ãã§æ¢ãŸããããã®å Žã§ãªããžããªå šäœãèµ°æ»ããã®ãæ£ããæé ã§ãã
3ä»¶ç®ïŒYouTrustããå®å
šç¡é³ãã§èœã¡ãŠããââã©ã€ãã©ãªã® process.exit()
çç¶ã åã8æ29æ¥ãXåŽã«ã€ããŠã¯ã3åç®ä»¥éã¯Discordã«ã¢ã©ãŒããåºãŠãããããšã確èªã§ããŸããããããYouTruståŽã¯Discordã«1ä»¶ãéç¥ãå±ããŠããŸããã§ããã6åèµ·åããŠ6å倱æããŠããã®ã«ãã¢ã©ãŒãã1ä»¶ããŒãä»¶ã
åå ã outreach-multi/src/yt/api.mjs ã®31è¡ç®ã« process.exit(3) ããããŸããã
// outreach-multi/src/yt/api.mjsïŒä¿®æ£åïŒ
async function fetchMessages(page) {
const resp = await browser.fetch(YT_API_ENDPOINT);
if (!resp.ok) {
console.error(`[yt/api] fetch failed: ${resp.status}`);
process.exit(3); // â ãã
}
return resp.json();
}
process.exit() ã¯äŸå€ã§ã¯ãããŸãããthrow ãšéããåŒã³åºãã¹ã¿ãã¯ãé¡ããŸãããåŒã³åºãå
ã® try/catch ã¯äžåºŠãå®è¡ãããŸããã
åŒã³åºãå ã®ã³ãŒãã¯ãããªã£ãŠããŸããã
// ãšã³ããªãã€ã³ãïŒä¿®æ£åïŒ
try {
const messages = await fetchMessages(page);
await handleMessages(messages);
} catch (err) {
// ãããèµ°ããšæã£ãŠãã
read_failures++;
if (read_failures >= ALERT_THRESHOLD) {
await discord.alert(`YouTrust failure: ${err.message}`);
}
}
process.exit(3) ãåŒã°ããç¬éãããŒãããã»ã¹ãå³çµäºããŸããcatch ãããã¯ã¯å°éããŸãããread_failures ã¯å ç®ãããŸãããDiscordã«ãäžãããŸãããlaunchdã¯ãããã»ã¹ãçµäºããããšèŠãŸããããã®çµäºã³ãŒããã©ãã«ãèšé²ãããªãçµè·¯ãéã£ãŠãããããå
šä»¶ãµã€ã¬ã³ãã«ãªããŸããã
äžæ¹ã§XåŽã3åç®ä»¥éã«ã¢ã©ãŒããåºããŠããã®ã¯ãXçšã®ã¢ãžã¥ãŒã«ã throw new Error(...) ã§æžãããŠããããã§ããcatch ãããã¯ãèµ°ããread_failures ãå ç®ãããéŸå€ãè¶
ããŠDiscordã«å±ãããåããChromeèµ·å倱æããšããçå ãåãã¢ãŒããã¯ãã£ææ³ãã§ãé
ç·ã1è¡éãã ãã§çæ¹ã¯é³Žãçæ¹ã¯å®å
šç¡é³ã«ãªããŸããã
çŽãæ¹ã
// â
AfterïŒã©ã€ãã©ãªå±€ã¯ throw ãããprocess.exit() ããªã
async function fetchMessages(page) {
const resp = await browser.fetch(YT_API_ENDPOINT);
if (!resp.ok) {
throw new Error(`yt/api fetch failed: ${resp.status}`);
}
return resp.json();
}
ç°å¢å€æ° YT_API_THROW=1 ã§åå²ãããæ¡ããããŸããããã©ã€ãã©ãªå±€ã« process.exit ãæžãçç±ããããããªããããåçŽã« throw ã«æžãçŽããŸããã
äžè¬åãšããŠæ®ã£ãããšã ã©ã€ãã©ãªå±€ã¯çµäºã®æš©éãæã£ãŠã¯ãããŸãããããã»ã¹ãçµããããŠããã®ã¯ãšã³ããªãã€ã³ãã ãã§ããäžã®å±€ã process.exit / sys.exit / os.Exit ãåŒãã ç¬éãäžã®å±€ãçšæãã芳枬ã»åŸå§æ«ã»éç¥ã¯ãã¹ãŠãã€ãã¹ãããŸãããã¬ãŒã ã¯ãŒã¯ãå€éšã©ã€ãã©ãªãããããã£ãŠããã±ãŒã¹ããããããæ°ããäŸåã远å ãããšãã« grep -r 'process\.exit' node_modules/<packagename>/ ã確èªããã¯ã»ãã€ããŠããŸãã
3ä»¶ã®å ±éãã¿ãŒã³
çç¶ã¯å šéšããã°ã¯ç·ãå®ç©ã¯ãŒãä»¶ãŸãã¯å€±æãã§ããããããåå ã®å±€ã¯éããŸãã
| ä»¶ | çç¶ | åå ã®å±€ | çŽãæ¹ |
|---|---|---|---|
| inbox-agent | DMè¿ä¿¡ãŒãã»ãã°å šç· | ã·ã§ã«ã¹ã¯ãªããã® echo è¡ | STATUS=$? ã§å
ã«éé¿ |
| note-autolike | ZIPæ·»ä»å€±æã3é±éæ°ã¥ããã | åäž | åäž + Discordã¢ã©ãŒã远å |
| YouTrust | 6åå šä»¶ç¡é³å€±æ | Node.jsã©ã€ãã©ãªå±€ã® process.exit | throw ã«æžãçŽã |
ã·ã§ã«ã®çœ ãšNode.jsã®çœ ã¯èŠãç®ãéããŸãããæ ¹ã£ãã¯åãã§ããã倱æã®ã·ã°ãã«ãåŒã³åºãå
ã«å±ãçµè·¯ãçšæããã«æžãããããšãããã¯ã®ã¬ãŒããåºãã£ãŠãããã©ããã¯ããã°ã®ç·ã§ã¯ãªããå®éã« exit 1 ãè¿ãããšãåŒã³åºãå
ãæ¢ãŸãããã宿ž¬ãããããããŸããã
ã€ãŸãããã€ã³ã
ååãšäžæ®µã§3ä»¶ã®ã€ã³ã·ãã³ãã远ããŸãããããåãçœ ãèžãå¯èœæ§ã®ããå Žæãã¯ãã£ãšãããŸããèªåã328æ¬ã®ã¹ã¯ãªãããèµ°æ»ããŠçºèŠããèœãšã穎ãšãClaude Codeã®ããã¯é ç·ã§ç¹°ãè¿ãåŒã£ããããã¿ãŒã³ãç¶²çŸ ããŸãã
ïŒ1ïŒecho "... $?" ã« $(...) ãæ··ãã£ãŠããè¡ã¯å
šéšã¢ãŠã
ã©ããªã«çãè¡ã§ããecho "[$(date)] done (exit $?)" ãšæžããããã®è¡ã¯æ§é äž (exit 0) ããåºããŸãããdate ã®ãµãã·ã§ã«ãæåããç¬éã« $? ã¯æžãæãããŸããã1è¡ã§æžãããããšããæ°æã¡ã¯æ£ããã®ã§ããããã®çµã¿åããã ãã¯çµ¶å¯Ÿã«æç«ããŸãããSTATUS=$? ãå
ã«åãããecho ã®äžãã $? ã远ãåºããã®ã©ã¡ãããããããŸããã
ïŒ2ïŒset -euo pipefail ã¯çŸåšã®ã·ã§ã«ã³ã³ããã¹ãã«ããå¹ããªã
run-with-flags-shell.sh ã®å
é ã« set -euo pipefail ããã£ãŠããJSã child_process.exec() ã« shell: true ãæž¡ããŠãã®ã¹ã¯ãªãããåŒã¶ãšã/bin/sh -c "..." ãšããã·ã§ã«ã©ãããŒãéã«æãŸããŸãããã® /bin/sh ã»ãã·ã§ã³ã«ã¯ pipefail ãåŒãç¶ãããŸãããã¹ã¯ãªããåäœã bash run-with-flags-shell.sh ã§åŒã¹ã°æ£ããåãã®ã«ãJSããåŒã¶ãšåããªãââãã¹ã¯ãªããã¯æ£ããæžããããçå®ã§ããJSã®åŒã³åºãæ¹ãå£ãããåå ã§ãã
ïŒ3ïŒ|| echo yes ãã©ãŒã«ããã¯ã¯ãã§ãã«ãŒã®æ
éã飲ã¿èŸŒã
run-with-flags-shell.sh ã®19è¡ç®ããããªã£ãŠããŸãã
ENABLED="$(node "${PLUGIN_ROOT}/scripts/hooks/check-hook-enabled.js" "$HOOK_ID" "$PROFILES_CSV" 2>/dev/null || echo yes)"
check-hook-enabled.js ãå£ããŠèœã¡ãå Žåã|| echo yes ãçºåã㊠ENABLED 㯠"yes" ã«ãªããŸããæå³çãªãã©ãŒã«ã»ãŒãèšèšã§ããããããã¯ç¢ºèªã¹ã¯ãªããèªäœãå£ããŠããã®ã«ããã¯ã¯æå¹ãšããŠé²ãããšããç¶æ
ãç¡é³ã§èµ·ããŸããããã¯ãæ£ããå€å®ãããŠãããã©ããã¯ããã®ãã§ãã«ãŒãæ£åžžã«åããŠããããšãåæã«ããŠããŸãã
ïŒ4ïŒã¹ã¯ãªãããèŠã€ãããªãå Žåã exit 0 ã§ééãã
åãã¹ã¯ãªããã®25ã30è¡ç®ãèŠãŠãã ããã
SCRIPT_PATH="${PLUGIN_ROOT}/${REL_SCRIPT_PATH}"
if [[ ! -f "$SCRIPT_PATH" ]]; then
echo "[Hook] Script not found for ${HOOK_ID}: ${SCRIPT_PATH}" >&2
printf '%s' "$INPUT"
exit 0
fi
ããã¯ã¹ã¯ãªããã®ãã¹ãééã£ãŠããŠããã¡ã€ã«ãååšããªãå Žåããšã©ãŒã¡ãã»ãŒãžã stderr ã«åºã㊠exit 0 ã§çµãããŸããClaudeã¯æ¢ãŸããŸãããèšå®ãã¹ããããšããããã¯ãåºãã£ãŠããªããã®ããããã¯ãæ£ããå€å®ããŠééããããã®ãããã°ã ãã§ã¯åºå¥ã§ããŸããã
ïŒ5ïŒprocess.exit() ã¯ã©ã€ãã©ãªå±€ã§åŒãã ç¬éã«èŠ³æž¬çµè·¯ãå
šæ»
ãã
outreach-multi/src/yt/api.mjs ã®31è¡ç®ããã®ãã¿ãŒã³ã§ãããåŒã³åºãå
ã® try/catch ãããã¯ã¯äžåºŠãå®è¡ããããread_failures ã«ãŠã³ã¿ãŒãå ç®ããããDiscordã«1ä»¶ãéç¥ãå±ããªãã£ããXåŽã throw new Error(...) ã§æžãããŠãããã鳎ã£ãŠããã®ãšå¯Ÿç
§çã§ããåãã¢ãŒããã¯ãã£ææ³ã§æžãã2ã€ã®ã¢ãžã¥ãŒã«ãã1è¡ã®éãã§ã鳎ã/å®å
šç¡é³ãã«åãããŸãã
ïŒ6ïŒPIPESTATUS ã¯bashåºæã»zshã§ã¯ååãéã
PIPESTATUS ã¯bashå°çšã®é
åã§ããzshã§ã¯ pipestatusïŒå°æåïŒãåçã®é
åãšããŠäœ¿ããŸãããã·ã§ãã³ã #!/bin/sh ã®ãŸãŸã§ã¯äœ¿ããªãã·ã§ã«ããããŸããrun-with-flags-shell.sh ã®ã·ã§ãã³ã¯ #!/usr/bin/env bash ãªã®ã§åé¡ãããŸããããããã¯ã¹ã¯ãªããåŽã sh ã§æžãããŠãããš PIPESTATUS ãåç
§ããŠã空ã«ãªããŸãã
ïŒ7ïŒlaunchdãåãåãçµäºã³ãŒããšã¹ã¯ãªããã®çµäºã³ãŒãã¯å¥ã®è©±
launchdã®ãžã§ããã°ã«åºãçµäºã³ãŒãã¯ããã®ãžã§ãã®æå€å±€ããã»ã¹ã®çµäºã³ãŒãã§ãã倿®µã®åŒã³åºããã§ãŒã³ãããå Žåãæå€å±€ã exit 0 ã§çµããã°ãå
åŽã§ã©ãã ã exit 1 ãèµ·ããŠããŠãlaunchd㯠exit 0 ãšèšé²ããŸãããlaunchdãå
šä»¶ exit 0ãã¯ãããã¯ãã§ãŒã³ã®æ«ç«¯ãŸã§å
šä»¶ exit 0ããšã€ã³ãŒã«ã§ã¯ãããŸããã
ïŒ8ïŒexecSync ã®ããã©ã«ãåäœããäŸå€ãåºãã°å€±æããšæã蟌ãèœãšã穎
execSync ã¯éãŒãã®çµäºã³ãŒãã§äŸå€ãæããŸãããshell: true ã§ãã€ãã䜿ã£ãŠããå Žåãã·ã§ã«ã©ãããŒåŽãçµäºã³ãŒã 0 ãè¿ãããšããããŸããäŸå€ãèµ·ããªãã£ãïŒæåãã§ã¯ãªããäŸå€ãèµ·ããªãã£ãïŒã·ã§ã«ã 0 ãè¿ãããã§ããå
åŽã®ã¹ã¯ãªããã®å€±æã¯ééããŸããã
ïŒ9ïŒæ°ããnpmããã±ãŒãžã process.exit() ãåŒã¶ã±ãŒã¹ããã
å€éšã©ã€ãã©ãªãå
éšã§ process.exit() ãåŒãã§ãããšãããšã³ããªãã€ã³ãã® try/catch ã¯ãã€ãã¹ãããŸããäŸåããã±ãŒãžã远å ãããšãã«ç¢ºèªããç¿æ
£ããªããšã远å åã¯é³Žã£ãŠããã¢ã©ãŒãã远å åŸãã鳎ããªããªãããšããçç¶ã§çºèŠããŸãã
ïŒ10ïŒããã°ãåºãŠãããã¯ãã¬ãŒããåºãã£ãŠãããã§ã¯ãªã
ã€ã³ã·ãã³ãã®æ¥ãDiscordã® #01_alerts ã«éç¥ãåºãŠããªãã£ãã®ã¯ã倱æãèµ·ããªãã£ããããã§ã¯ãããŸããã§ãããã倱æã®ã³ãŒããã¢ã©ãŒãã鳎ããçµè·¯ãŸã§å±ããŠããªãã£ããããã§ãããã°ãåºãïŒã¹ã¯ãªãããèµ·åãããã§ãããã¬ãŒããåºããïŒçµäºã³ãŒããåŒã³åºãå
ãŸã§äŒæãããã§ãããã®2ã€ã¯å¥ã®äºå®ã§ãã
ïŒ11ïŒgrep ã§æ©æ¢°çã«æœ°ããã || rc=$? åã¯äººéã®ç®ãèŠã
æ€åºã¯ãšãª grep -rn 'exit \$?' --include='*.sh' ~/dev ~/.claude/scripts | grep '\$(' ã¯æå¹ã§ãããx="$(cmd)" || rc=$? ãšããåœ¢ã¯æ£ããæžãæ¹ãªã®ã§ãããè¡ããé€å€ãå¿
èŠã§ãã代å
¥æã®çµäºã¹ããŒã¿ã¹ã¯ã³ãã³ã眮æã®ããã«ãªããããx="$(node ...)" ã®æ¬¡ã®è¡ã§ $? ãèªãã®ã¯æ£ãããecho è¡ã®äžã§ $(...) ãš $? ãæ··ããŠããã±ãŒã¹ã ããåé¡ã§ããèªåã§å
šä»¶ã¯æœ°ããããããè¡ãç®èŠãã1ã¹ããããæ®ããŸãã
ïŒ12ïŒYT_API_THROW ã§ throw ã«åãæ¿ããŠããå®éã«å€±æãèµ·ãããŸã§ã¯æªå®èšŒ
äžæ®µã§æžãã YouTrust ã®ä¿®æ£ââprocess.exit(3) ã throw new Error(...) ã«æžãçŽãââã¯ãnode --check ãš grep ã§éçã«ç¢ºèªããŠããŸãããå®éã« Chrome ãèµ·å倱æãããšãã« read_failures ãå ç®ãã㊠Discord ã«åºããã¯æ¬¡ã«èµ·å倱æãèµ·ããŠåããŠå®èšŒãããŸãããã³ãŒãã¯æ£ããããšãçµè·¯ãæ¬çªã§éã£ããã¯å¥ã®äºå®ã§ãã
ãã¹ããã©ã¯ãã£ã¹
3ä»¶ã®ã€ã³ã·ãã³ããš328æ¬ã®èµ°æ»ããåŸãæèšããæ¬¡ã«åãç°å¢ãäœããšãã®æéãšããŠæŽçããŸãã
1. STATUS=$? ãå
ã«åãã«ãŒã«ã身äœã«æã¿èŸŒãŸãã
ã³ãã³ãã®çŽåŸã§ $? ãåç
§ããããªããå¿
ã1è¡ã§ STATUS=$? ãšéé¿ããããecho ã®äžã§ $(...) ãš $? ãåå±
ãããããšã¯ç©ççã«çŠæ¢ããããã·ã§ã«ã¹ã¯ãªãããæžãïŒãã®çµã¿åãããé¿ããããåå°ã«ããã
2. å
šã·ã§ã«ã¹ã¯ãªããã®å
é ã« set -euo pipefail ãæžã
æ°ããã¹ã¯ãªãããäœããšããæåã®2è¡ã¯åžžã«
#!/usr/bin/env bash
set -euo pipefail
ã«ãããæ¢åã¹ã¯ãªãããè§Šããšãã¯ããã¡ã€ã«ãéãããå é ããŸã確èªãããããããªãã¹ã¯ãªããã¯ãç¡é³ã§å€±æããæºåãã§ããŠããããšæã£ãŠèªãã
3. JSããå€éšã¹ã¯ãªãããåŒã¶ãšã㯠spawn ã䜿ã
child_process.exec() ã« shell: true ãæž¡ãåŒã³åºãã¯ãã·ã§ã«ã©ãããŒãçµäºã³ãŒããæ¡ãæœ°ãå¯èœæ§ããããŸããchild_process.spawn() ã shell: true ãªãã§äœ¿ããš execve(2) ã§çŽæ¥èµ·åãããŸããclose ã€ãã³ãã® code åŒæ°ãçµäºã³ãŒãã§ããnull ã®ãšã㯠signal åŒæ°ã§ã·ã°ãã«çµäºã確èªããŸãã
4. ã©ã€ãã©ãªå±€ã« process.exit() / sys.exit() / os.Exit() ãæžããªã
ããã»ã¹ãçµäºããŠããã®ã¯ãšã³ããªãã€ã³ãã ãã§ããã©ã€ãã©ãªã process.exit ãåŒãã ç¬éããšã³ããªãã€ã³ããçšæãã catch ãããã¯ã»éç¥ã»ã«ãŠã³ã¿ãŒå ç®ã»åŸå§æ«ãå
šéšãã€ãã¹ãããŸããã©ã€ãã©ãªå±€ã¯äŸå€ã throw ããŠäžã«æž¡ãããéåã§ãã
5. æ°ããäŸåããã±ãŒãžã远å ãããšã㯠process.exit ã®æç¡ã確èªãã
grep -r 'process\.exit' node_modules/<packagename>/
ãã®ã¯ãšãªã远å åã«èµ°ãããç¿æ
£ãã€ããŸããã©ã€ãã©ãªãå
éšã§ process.exit ãåŒãã§ããå Žåããšã³ããªãã€ã³ãã® catch ãããã¯ããã€ãã¹ããŸãã远å åŸãããã¢ã©ãŒãã鳎ããªããªã£ãããšããçç¶ã§çºèŠãããããè¿œå æã«ç¢ºèªããã»ããå®ãã§ãã
6. æå°ã® exit 1 ãããŒã§ãã¬ãŒããåºããããã宿ž¬ãã
ããã¯ãæžããããé ç·ãä¿¡é Œããåã«å¿ ã宿ž¬ããŸãã
#!/usr/bin/env bash
# /tmp/test-hook.sh
exit 1
ãã®ãããŒã settings.json ã®Stopããã¯ã«ç»é²ããŠãClaudeã«äœãçããããŸãããããã¯ããããã¯ããŸããããšããã¡ãã»ãŒãžãåºãã°é
ç·ã¯çããŠããŸããåºãªããã°ãåŒã³åºããã§ãŒã³ã®ã©ããã§çµäºã³ãŒããæ»ãã§ããŸãããã°ã®ç·ãä¿¡é Œããããå
ã«ããã®1ã¹ããããèžã¿ãŸãã
7. 1ä»¶èŠã€ããç¬éã«æšªå±éãã
åãã³ãŒããã¿ãŒã³ã¯å¿
ãè€æ°ç®æã«ãããŸããinbox-agent/run-medium.sh ã§çºèŠããæç¹ã§å³åº§ã«å
šäœãèµ°æ»ãããããnote-autolike/scripts/retry-attach-kit.sh ã®æænoteç¹å
žZIPæ·»ä»å€±æã3é±é以äžç¶ããŠããããšãçºèŠã§ããŸããã1ä»¶ä¿®æ£ã§æ¢ããŠãããã賌å
¥è
ã¯ä»ãç¹å
žãåãåããŠããªãã£ããããããŸããã
æ€åºã¯ãšãªã¯ãã®ãŸãŸäœ¿ããŸãã
grep -rn 'exit \$?' --include='*.sh' ~/dev ~/.claude/scripts | grep '\$('
ãããè¡ãç®èŠã㊠x="$(cmd)" || rc=$? åãé€å€ããã°ãæ®ãã¯å
šéšä¿®æ£å¯Ÿè±¡ã§ãã
8. ã¢ã©ãŒããã鳎ããªãã£ãããå¥å šã®èšŒæ ã«ããªã
XåŽã¯3åç®ä»¥éã«Discordã® #01_alerts ã«éç¥ãæ¥ãŠããŸãããYouTruståŽã¯6åå
šä»¶èµ·å倱æã§ã1ä»¶ãæ¥ãŸããã§ããããDiscordãéãã ã£ããã¯ãåé¡ããªãã£ããã§ã¯ãªããã¢ã©ãŒãã鳎ããçµè·¯ãŸã§å€±æã³ãŒããå±ããªãã£ããå¯èœæ§ãå«ã¿ãŸããã¢ã©ãŒãã远å ãããšãã¯ãå®éã«ã¢ã©ãŒãã鳎ãçµè·¯ãäžåºŠæ¬çªã«è¿ã圢ã§éããŠãããç£èŠãæ©èœããŠããããšèšããŸãã
9. run-with-flags-shell.sh ã®ã¹ã¯ãªããæªçºèŠãã¹ãææ¡ããŠãã
å®ã³ãŒãã®27ã30è¡ç®ã§ã¯ãã¹ã¯ãªãããã¡ã€ã«ãååšããªãå Žåã« stderr ãžãšã©ãŒãåºã㊠exit 0 ã§çµãããŸããããã¯ã®èšå®ãã¹ãééããå Žåããšã©ãŒã¯stderrã«åºãŸãããClaudeã¯æ¢ãŸããŸãããããã¯ããå¹ããŠããªãããšæãããšãããŸã stderr ãã°ã確èªããŸãã
10. check-hook-enabled.js ã® || echo yes ãã©ãŒã«ããã¯ãç¥ã£ãŠãã
run-with-flags-shell.sh ã®19è¡ç®ã®ãã©ãŒã«ããã¯ã¯ãããã¯ç¢ºèªã¹ã¯ãªãããå£ããŠããŠãããã¯ãæå¹ãšããŠé²ããèšèšã§ããããã¯æå³çãªãã©ãŒã«ã»ãŒãã§ãããããã§ãã«ãŒèªäœãå£ããŠããããšããç¶æ
ãç¡é³ã§é²ã¿ãŸããããã¯ãæåŸ
ã©ããã«ç¡å¹åãããŠããªãå Žåããã®ãã§ãã«ãŒãæ£åžžã«åããŠãããã確èªããŸãã
11. PIPESTATUS ã䜿ããªãã·ã§ãã³ãšç°å¢ãæãã
PIPESTATUS ã¯bashåºæã§ãã#!/bin/sh ã®ã¹ã¯ãªããã§ã¯äœ¿ããªãã·ã§ã«ããããŸãããã€ãã©ã€ã³ã®åã³ãã³ãã®çµäºã³ãŒããåå¥ã«èšé²ãããå Žåã¯ãã·ã§ãã³ã #!/usr/bin/env bash ã«ã㊠PIPESTATUS ãæç€ºããŸãã
printf '%s' "$INPUT" | "$SCRIPT_PATH" "$HOOK_PHASE"
PIPE_STATUS=("${PIPESTATUS[@]}")
# PIPE_STATUS[1] ã $SCRIPT_PATH ã®çµäºã³ãŒã
pipefail ãããã° $SCRIPT_PATH ã®å€±æã¯èªåçã«ã¹ã¯ãªããã®çµäºã³ãŒãã«äŒæããŸããããã©ã¡ãã®ã³ãã³ããèœã¡ããããèšé²ãã°ã«æ®ãèšèšãªã PIPESTATUS ãæç€ºããŸãã
12. launchd ã®å
šä»¶ exit 0 ã1次æ
å ±ãšããŠæ±ããªã
launchdãèšé²ããçµäºã³ãŒãã¯æå€å±€ããã»ã¹ã®ãã®ã§ãã倿®µã©ãããŒã®ç°å¢ã§ã¯ãlaunchdã exit 0ãïŒãå
åŽãå
šéš exit 0ãã§ã¯ãããŸãããå®éã®æåŠã¯ããžã§ããå®è¡ããçµæââè¿ä¿¡ä»¶æ°ã»æ·»ä»ãã¡ã€ã«ã®æç¡ã»APIã¬ã¹ãã³ã¹ââã宿ž¬å€ã§ç¢ºèªããŸãã
13. ã³ãŒãããæ£ããæžããŠããããšãçµè·¯ãæ¬çªã§éã£ãããåºå¥ãã
ä¿®æ£åŸã®ã³ãŒããæ§æçã«æ£ãããŠããå®éã«ãšã©ãŒã±ãŒã¹ã®ãã¹ãéãã®ã¯ãæ¬¡ã«æ¬çªã§å€±æãèµ·ãããšããã§ãããã¹ãç°å¢ã§å€±æãåçŸãããããæå³çã«å€±æãèµ·ãããŠã¢ã©ãŒããå±ããã確èªããŠãããä¿®æ£å®äºããšèšããŸãããã³ãŒãã¯æ£ãããã¯ãåäœç¢ºèªæžã¿ãã§ã¯ãããŸããã
ãŸãšã
åé¡ã®æ§é ãã²ãšèšã§èšããšã**ã倱æã¯èµ·ããŠããããã ãçµäºã³ãŒããåŒã³åºãå ã«çããŠããªãã£ãã ãã**ã§ãã
inbox-agent/run-medium.sh ã® echo "[$(date)] $LANE done (exit $?)" ãšãã1è¡ã¯ãã·ã§ã«ã¹ã¯ãªãããšããŠæ§æãšã©ãŒããªãããã°ãåºãŠããŠãèŠãç®ã«ã¯æ£åžžã§ãããã§ããã®è¡ãå°åããŠãã (exit 0) ã¯çŽåã® node ã®çµæã§ã¯ãªãã$(date) ãæåããçµæã§ããã28æéåã®å¶æ¥DMè¿ä¿¡ããŒãä»¶ã«ãªã£ãåå ã¯ããã®1è¡ããç·ãå°åããã ãã®ã³ãŒããã ã£ãããšã§ãã
outreach-multi/src/yt/api.mjs:31 ã® process.exit(3) ãåãã§ãããšã©ãŒãæ€ç¥ããŠãããã§ãæ€ç¥ããå Žæã§ããã»ã¹ãçµäºãããããã«ããšã³ããªãã€ã³ããçšæããŠããã«ãŠã³ã¿ãŒãéç¥ãåããªãã£ããåãChromeèµ·å倱æãšããçå ã§ãXåŽã¯3åç®ä»¥éã«Discordã鳎ããYouTruståŽã¯6åå
šä»¶å®å
šç¡é³ã«ãªããŸãããå·®ã¯é
ç·ã®1è¡ã ãã§ãã
èªååç°å¢ã®ãå¥å
šãããæž¬ããšãããã°ã®ç·ã®æ°ã¯ä¿¡çšã§ããŸãããä¿¡çšã§ããã®ã¯ãå®éã« exit 1 ãè¿ãããšãããã®ä¿¡å·ãåŒã³åºãå
ã®Claude CodeãŸã§å±ããŠãããã¯ãèµ·ãããããšãã宿ž¬ã ãã§ãã171æ¬ã®launchdãžã§ããšè€æ°ã®Claude Codeã»ãã·ã§ã³ãåæã«åãç°å¢ã§ããã®å®æž¬ãæžãŸããŠããªãããã¯ã¯ã¬ãŒãã¬ãŒã«ã®ãªãåŽãšåãã§ãã
328æ¬ã®ã¹ã¯ãªãããèµ°æ»ããŠ3ä»¶ã®åãçœ ãèŠã€ãã3ãªããžããªãžã®ä¿®æ£ãã³ããããããŸã§æ°æéããããŸãããããããæænoteã®è³Œå ¥è ã3é±é以äžç¹å žZIPãããŠã³ããŒãã§ããŠããªãã£ãããšããäºå®ã¯ãèµ°æ»ããããçºèŠããŸããã1ä»¶ã§æ¢ããŠãããä»ãç·ã䞊ãã§ããã¯ãã§ãã
çµäºã³ãŒãã¯ãäŒæçµè·¯ã®å
šå±€ãæ£ããæžãããŠããªããšå±ããŸãããã·ã§ã«ã® $? åé¡ãJSã® shell: true åé¡ãã©ã€ãã©ãªå±€ã® process.exit åé¡ââã©ããåãæ ¹ã£ãã§ããããã¯ãæžããããæå°ã® exit 1 ãããŒã§å®éã«åºãããã確ããããããã ãã§ãä»åã®ãããªæ²é»ãã°ã®å€§åã¯äºåã«æœ°ããŸãã
ä»çµã¿ã®å šäœåã»æ120äžã®å èš³ã»30æ¥æé ã¯æænoteã«ãŸãšããŠããŸãã ð Claude CodeèªåŸç°å¢ã§ãå®éã©ã皌ãã â ä»çµã¿ã»å®äŸã»å§ãæ¹ã»ãµããŒã
LilyïŒ@bokuwalilyïŒâ å人éçºè ãClaude Code ã§èªåååºç€ãçµã¿ãªãããiOSã¢ããªãWebãµãŒãã¹ãéç£ããŠããŸã
- AIã§ãå¯ãŠãŠãåãä»çµã¿ããäœã£ãŠæ120äžã«ãã話㯠noteã®ææèšäº ã«ð°
- OSS: github.com/bokuwalily ð
- ææ°æ å ±ã»ãåãåãã㯠X @bokuwalily ãžð
- AIå°å ¥ã»èªååã®çžè«ãšå®è£ ãã³ãã¬7æ¬ã®é åžã¯ å ¬åŒLINE ããð¬
çããã® â€ïž ãã·ã§ã¢ãå±ã¿ã«ãªããŸãïŒ