Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/).

## [0.61.0] - 2026-06-12

LLM 性能監査(#121)P2 の第 1 弾(#111)。tmux-hooks のハードブロックをリマインダーに降格した。

### Changed
- **tmux-hooks のハードブロックを非ブロックのリマインダーに降格(#111)**: TMUX 外での dev サーバー起動(`npm run dev` 等)を exit 2 でブロックしていた挙動を撤廃。現行 Claude Code はネイティブの background 実行(`run_in_background`)とログ取得を備えており、ブロックはむしろネイティブ機能の利用を妨害していた。新挙動: (1) `run_in_background=true` は即許可(出力なし)、(2) TMUX 外の foreground dev サーバーは exit 0 + stderr 1 行のリマインダー(run_in_background を第一候補、永続セッションが必要なら tmux を代替として提示)、(3) npm test / cargo build / docker 等への「Consider running in tmux」定常 advisory は削除(高頻度コマンドへの情報量ゼロのノイズ)

## [0.60.0] - 2026-06-12

LLM 性能監査(#121)P1 の最終弾(#110)。pre-compact-commit を opt-in 化し、履歴を汚さない stash 方式に書き換えた。
Expand Down
2 changes: 1 addition & 1 deletion README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ Hooks are automated safety checks that run automatically when Claude Code execut
|---|---|
| **Safety Net** | Blocks destructive git/filesystem commands (`git reset --hard`, `rm -rf`, `git push --force`, etc.) before execution |
| **Auto Update** | Checks for starter kit updates on session start and applies them in the background |
| Tmux Reminder | Suggests tmux for long-running commands |
| Tmux Reminder | Suggests run_in_background for foreground dev servers (non-blocking) |
| Git Push Review | Pauses before git push for code review |
| Doc Blocker | Prevents creation of unnecessary .md/.txt files |
| Prettier Auto-format | Formats JS/TS files after edits |
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ URL・公式ドキュメント・ブログ・ニュース・OSS ページを読
|---|---|
| **Safety Net** | **破壊的な git/ファイルシステムコマンド(`git reset --hard`、`rm -rf` 等)を実行前にブロック** |
| **自動アップデート** | **セッション開始時にスターターキットの最新版を自動で適用** |
| Tmux リマインダー | 長時間コマンドに tmux の使用を提案 |
| Tmux リマインダー | foreground の dev サーバーに run_in_background を提案(非ブロック) |
| Git Push レビュー | コードを共有する前に確認を促す |
| Doc ブロッカー | 不要なドキュメントファイルの作成を防止 |
| Prettier 自動フォーマット | JS/TS ファイルを自動で見た目を整える |
Expand Down
2 changes: 1 addition & 1 deletion docs/wizard-config-mapping.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ These flags are used to merge the corresponding `features/*/hooks.json` fragment
| `ENABLE_SAFETY_NET` | Safety Net | Block destructive commands | Yes |
| `ENABLE_AUTO_UPDATE` | Auto Update | Check for starter kit updates on session start | Yes |
| `ENABLE_WEB_CONTENT_UPDATE` | Web Content Update | Check web extraction skill dependency updates | Yes |
| `ENABLE_TMUX_HOOKS` | Tmux Reminder | Encourage tmux for long-running work | Yes |
| `ENABLE_TMUX_HOOKS` | Tmux Reminder | Suggest run_in_background for foreground dev servers (non-blocking) | Yes |
| `ENABLE_GIT_PUSH_REVIEW` | Git Push Review | Pause before push and open a diff | Yes |
| `ENABLE_DOC_BLOCKER` | Doc Blocker | Prevent unnecessary `.md` / `.txt` files | Yes |
| `ENABLE_PRETTIER_HOOKS` | Prettier Auto-format | Format JS / TS edits | Yes |
Expand Down
2 changes: 1 addition & 1 deletion docs/wizard-config-mapping.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
| `ENABLE_SAFETY_NET` | Safety Net | 危険なコマンドの遮断 | はい |
| `ENABLE_AUTO_UPDATE` | Auto Update | セッション開始時の更新確認 | はい |
| `ENABLE_WEB_CONTENT_UPDATE` | Web Content Update | Web 取得スキル依存の更新確認 | はい |
| `ENABLE_TMUX_HOOKS` | Tmux Reminder | 長時間処理を tmux に誘導 | はい |
| `ENABLE_TMUX_HOOKS` | Tmux Reminder | foreground の dev サーバーに run_in_background を提案(非ブロック) | はい |
| `ENABLE_GIT_PUSH_REVIEW` | Git Push Review | push 前に差分確認 | はい |
| `ENABLE_DOC_BLOCKER` | Doc Blocker | 不要な `.md` / `.txt` 作成を抑制 | はい |
| `ENABLE_PRETTIER_HOOKS` | Prettier Auto-format | JS / TS 編集後の整形 | はい |
Expand Down
8 changes: 6 additions & 2 deletions features/tmux-hooks/feature.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
{
"name": "tmux-hooks",
"displayName": "Tmux Reminder",
"description": "Block dev servers outside tmux and suggest tmux for long-running commands",
"description": "Non-blocking reminder: suggest run_in_background (or tmux) for foreground dev servers",
"category": "hook",
"default": true,
"profiles": { "minimal": false, "standard": true, "full": true },
"profiles": {
"minimal": false,
"standard": true,
"full": true
},
"dependencies": [],
"conflicts": []
}
17 changes: 9 additions & 8 deletions features/tmux-hooks/scripts/check-bash.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@ set -euo pipefail

input="$(cat)"
cmd="$(printf '%s' "$input" | jq -r '.tool_input.command // ""')"
run_in_background="$(printf '%s' "$input" | jq -r '.tool_input.run_in_background // false')"

# Native background execution manages the process and its logs — nothing to add.
if [[ "$run_in_background" == "true" ]]; then
exit 0
fi

# Foreground dev server outside tmux: non-blocking reminder only.
if printf '%s' "$cmd" | grep -qE '(npm run dev|pnpm( run)? dev|yarn dev|bun run dev)' \
&& [[ -z "${TMUX:-}" ]] \
&& ! printf '%s' "$cmd" | grep -qE 'tmux[[:space:]]+(new-session|new|send-keys)'; then
echo '[Hook] BLOCKED: Dev server must run in tmux for log access' >&2
echo '[Hook] Use: tmux new-session -d -s dev "npm run dev"' >&2
echo '[Hook] Then: tmux attach -t dev' >&2
exit 2
echo '[Hook] Reminder: prefer run_in_background for dev servers (or tmux new-session for a persistent session)' >&2

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use a visible hook response for the reminder

When this PreToolUse hook sees a foreground dev server outside tmux, it writes the reminder to stderr but then falls through to exit 0. In Claude Code command hooks, exit 0 only processes stdout JSON and otherwise keeps output in debug; stderr is fed back for exit 2 or non-zero hook errors per the hooks reference, so the intended non-blocking reminder is silent in real sessions even though the new tests inspect the script's raw stderr. Please return a documented JSON response such as systemMessage/hookSpecificOutput.additionalContext, or another supported non-blocking signal, instead.

Useful? React with 👍 / 👎.

fi

if printf '%s' "$cmd" | grep -qE '(npm (install|test)|pnpm (install|test)|yarn (install|test)|bun (install|test)|cargo build|make|docker|pytest|vitest|playwright)' \
&& [[ -z "${TMUX:-}" ]]; then
echo '[Hook] Consider running in tmux for session persistence' >&2
fi
exit 0
2 changes: 1 addition & 1 deletion i18n/en/strings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ STR_HOOKS_TITLE="Select hooks to enable (enter numbers separated by spaces):"
STR_HOOKS_SAFETY_NET="Safety Net - Block destructive git/filesystem commands (cc-safety-net)"
STR_HOOKS_AUTO_UPDATE="Auto Update - Automatically update starter kit on session start"
STR_HOOKS_WEB_CONTENT_UPDATE="Web Content Update - Auto-update web-content-extraction skill deps on session start (opt-in)"
STR_HOOKS_TMUX="Tmux Reminder - Suggest tmux for long-running commands"
STR_HOOKS_TMUX="Tmux Reminder - Suggest run_in_background for foreground dev servers (non-blocking)"
STR_HOOKS_GIT_PUSH="Git Push Review - Pause before git push for review"
STR_HOOKS_DOC_BLOCK="Doc Blocker - Block creation of random .md/.txt files"
STR_HOOKS_PRETTIER="Prettier Auto-format - Format JS/TS files after edits"
Expand Down
2 changes: 1 addition & 1 deletion i18n/ja/strings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ STR_HOOKS_TITLE="有効にするフックを選択してください(番号を
STR_HOOKS_SAFETY_NET="Safety Net - 破壊的な git/ファイルシステムコマンドをブロック (cc-safety-net)"
STR_HOOKS_AUTO_UPDATE="自動アップデート - セッション開始時にスターターキットを自動更新"
STR_HOOKS_WEB_CONTENT_UPDATE="Web取得スキル更新 - セッション開始時に web-content-extraction の依存を自動更新(opt-in)"
STR_HOOKS_TMUX="Tmux リマインダー - 長時間コマンドに tmux を提案"
STR_HOOKS_TMUX="Tmux リマインダー - foreground の dev サーバーに run_in_background を提案(非ブロック)"
STR_HOOKS_GIT_PUSH="Git Push レビュー - push 前に一時停止してレビュー"
STR_HOOKS_DOC_BLOCK="ドキュメントブロッカー - 不要な .md/.txt ファイルの作成を防止"
STR_HOOKS_PRETTIER="Prettier 自動フォーマット - JS/TS ファイルを編集後にフォーマット"
Expand Down
6 changes: 3 additions & 3 deletions tests/unit/test-hook-fixtures.sh
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,13 @@ bash "$PROJECT_DIR/features/git-push-review/scripts/remind.sh" <"$_pre_push_fixt
bash "$PROJECT_DIR/features/feature-recommendation/scripts/check-pending.sh" <"$_hook_fixture_dir/sessionstart-startup.json" >/dev/null 2>/dev/null || _script_smoke_ok=false

_tmux_rc=0
bash "$PROJECT_DIR/features/tmux-hooks/scripts/check-bash.sh" <"$_pre_dev_fixture" >/dev/null 2>"$_hook_tmp/tmux.err" || _tmux_rc=$?
env -u TMUX bash "$PROJECT_DIR/features/tmux-hooks/scripts/check-bash.sh" <"$_pre_dev_fixture" >/dev/null 2>"$_hook_tmp/tmux.err" || _tmux_rc=$?

if [[ "$_script_smoke_ok" == "true" ]] \
&& assert_matches "console\\.log found" "$(cat "$_hook_tmp/console.err")" \
&& assert_matches "Reminder: review your staged changes" "$(cat "$_hook_tmp/push.err")" \
&& [[ "$_tmux_rc" -eq 2 ]] \
&& assert_matches "Dev server must run in tmux" "$(cat "$_hook_tmp/tmux.err")"; then
&& [[ "$_tmux_rc" -eq 0 ]] \
&& assert_matches "prefer run_in_background" "$(cat "$_hook_tmp/tmux.err")"; then
pass "hook-fixtures: distributed hook scripts consume real-schema fixtures"
else
fail "hook-fixtures: distributed hook scripts should consume real-schema fixtures"
Expand Down
59 changes: 59 additions & 0 deletions tests/unit/test-runtime-hooks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,62 @@
fail "$test_name"
fi
}


{
test_name="tmux-hooks: run_in_background dev server passes without any output"
_th_tmp="$(mktemp -d)"
_SETUP_TMP_FILES+=("$_th_tmp")
_th_rc=0
printf '{"tool_name":"Bash","tool_input":{"command":"%s","run_in_background":true}}' "npm run dev" \
| env -u TMUX bash "$PROJECT_DIR/features/tmux-hooks/scripts/check-bash.sh" >/dev/null 2>"$_th_tmp/bg.err" || _th_rc=$?
if [[ "$_th_rc" -eq 0 ]] && [[ ! -s "$_th_tmp/bg.err" ]]; then
pass "$test_name"
else
fail "$test_name"
fi
}

{
test_name="tmux-hooks: foreground dev server is a non-blocking reminder (no exit 2)"
_th_tmp2="$(mktemp -d)"
_SETUP_TMP_FILES+=("$_th_tmp2")
_th_rc=0
printf '{"tool_name":"Bash","tool_input":{"command":"%s"}}' "npm run dev" \
| env -u TMUX bash "$PROJECT_DIR/features/tmux-hooks/scripts/check-bash.sh" >/dev/null 2>"$_th_tmp2/fg.err" || _th_rc=$?
if [[ "$_th_rc" -eq 0 ]] \
&& grep -q "prefer run_in_background" "$_th_tmp2/fg.err" \
&& ! grep -q "BLOCKED" "$_th_tmp2/fg.err"; then
pass "$test_name"
else
fail "$test_name"
fi
}

{
test_name="tmux-hooks: build/test commands no longer trigger advisory noise"
_th_tmp3="$(mktemp -d)"
_SETUP_TMP_FILES+=("$_th_tmp3")
_th_rc=0
printf '{"tool_name":"Bash","tool_input":{"command":"npm test"}}' \
| env -u TMUX bash "$PROJECT_DIR/features/tmux-hooks/scripts/check-bash.sh" >/dev/null 2>"$_th_tmp3/adv.err" || _th_rc=$?
if [[ "$_th_rc" -eq 0 ]] && [[ ! -s "$_th_tmp3/adv.err" ]]; then
pass "$test_name"
else
fail "$test_name"
fi
}

{
test_name="tmux-hooks: dev server inside tmux session stays silent"
_th_tmp4="$(mktemp -d)"
_SETUP_TMP_FILES+=("$_th_tmp4")
_th_rc=0
printf '{"tool_name":"Bash","tool_input":{"command":"npm run %s"}}' "dev" \
| env TMUX=fake-session bash "$PROJECT_DIR/features/tmux-hooks/scripts/check-bash.sh" >/dev/null 2>"$_th_tmp4/in-tmux.err" || _th_rc=$?
if [[ "$_th_rc" -eq 0 ]] && [[ ! -s "$_th_tmp4/in-tmux.err" ]]; then
pass "$test_name"
else
fail "$test_name"
fi
}
Loading