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
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,24 @@ 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.71.0] - 2026-06-12

v0.57.0〜v0.70.0 の累積差分に対する multi-agent 通しレビュー(8 次元 + 14 Issue 受け入れ照合 + 敵対的検証)のフォローアップ(#138)。

### Fixed
- **custom プロファイルの update で agent-teams env が無言で削除される問題を修正(#138)**: update 経路は非対話デフォルト補完を通らず、custom プロファイルには conf ファイルが無いため、`ENABLE_AGENT_TEAMS` が空のまま fragment 不注入 → 3-way merge でキー削除となっていた。`_restore_config_from_manifest` に後発キーのデフォルト補完を追加
- **doc-blocker の拡張子ゲートを case-insensitive 化(#138)**: `SUMMARY.MD` / `NOTES.TXT` のような大文字拡張子が ask 確認をバイパスしていた(slop 名判定は nocasematch 済みだったが外側の拡張子ゲートが case-sensitive だった)
- **`_strip_retired_hook_entries` のマッチを `/.claude/hooks/<feature>/` にアンカー強化(#138)**: 廃止 feature と同名のディレクトリ配下にあるユーザー自作 hook(例: `~/dotfiles/hooks/memory-persistence/`)を誤って除去し得た非アンカー substring マッチを修正(回帰テスト付き)

### Added
- **agent-teams をウィザード・`--hooks` CSV で切替可能に(#138、#120 の受け入れギャップ解消)**: `HOOK_KEYS` / `HOOK_TOKENS`(トークン `agent-teams`)/ `HOOK_LABELS` に登録し、custom プロファイルや `--hooks` 指定でオフにできるようにした。README の `--hooks` 例にも追加(`--hooks` は明示列挙のため、リストに含めない場合は無効化される点に注意)
- agent teams GA 時の env フラグ除去トラッキング Issue #139 を起票(#120 の受け入れギャップ解消)
- **テスト追加**: effortLevel ピン解除の merge 挙動 2 ケース(未変更→キー削除 / 上書き済み→値保持)、spec-kit partial の `INSTALL_COMMANDS` ゲート回帰テスト、retired 4 feature の一括 strip + ユーザー同名ディレクトリ保護のテスト(unit 計 348)

### Changed
- **CLAUDE.md 注入の体裁改善(#138)**: 無効 feature のマーカー行を空行で残す replace モードから行ごと削除する delete モードに変更(minimal プロファイルの連続空行を解消)。各 partial 先頭に区切り空行を追加し、partial 同士の密着を解消
- **ドキュメント残骸の掃除(#138)**: README ja のプロファイル比較表(メモリ行・旧フック数)・フック節見出し「15個」→「11個」・エディタ注記の廃止 hook 言及、README en のプロファイル表 Memory 列、profiles/standard.conf ヘッダコメント、リポジトリ CLAUDE.md(Inline hooks 例・Doc Size Guard 記述)、docs/GUIDES/hooks-reference.md の Compaction 節、lib/deploy.sh の spec-kit 注入ブロックの誤コメント

## [0.70.0] - 2026-06-12

LLM 性能監査(#121)の最終弾(#120)。配布設定の世代依存ピンを整理した。これで監査計画 P1-P4 の全 14 Issue(#107〜#120)が完了。
Expand Down
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ Each feature in `features/*/` has a `hooks.json` containing Claude Code hook def
**IMPORTANT: Hook types (`SessionStart`, `SessionEnd`, `PreToolUse`, `PostToolUse`, `PreCompact`, `PostCompact`, `Stop`, `Notification`) MUST be nested inside a `"hooks"` key in hooks.json.** Claude Code reads hooks from `settings.json.hooks.*`, not from the top level. Top-level settings keys (`env`, `statusLine`, etc.) remain at the root.

Three fragment styles exist:
- **Inline hooks**: bash commands embedded as escaped JSON strings in `hooks.json` `"command"` fields, nested inside `"hooks"` (e.g., `features/tmux-hooks/hooks.json`)
- **Inline hooks**: bash commands embedded as escaped JSON strings in `hooks.json` `"command"` fields, nested inside `"hooks"` (e.g., `features/pre-compact-commit/hooks.json`)
- **External script hooks**: `hooks.json` references a script path with `__HOME__` token inside `"hooks"`, (e.g., `"hooks": {"PostToolUse": [{"hooks": [{"command": "__HOME__/.claude/hooks/doc-size-guard/check-doc-size.sh"}]}]}`). These scripts are deployed by `deploy_hook_scripts()` to `~/.claude/hooks/<feature>/` with `chmod +x`. Both `.sh` and `.py` scripts are supported.
- **Top-level settings**: `hooks.json` can contain any top-level settings key alongside `"hooks"`. The jq deep-merge applies at root level, so `{"statusLine": {...}}` and `{"env": {...}}` merge correctly (e.g., `features/statusline/hooks.json`, `features/safety-net/hooks.json`).

Expand Down Expand Up @@ -262,7 +262,7 @@ Multiple features can safely use the same hook type (e.g., `PreCompact`, `PostCo
- **Safety Net**: `cc-safety-net` PreToolUse hook blocks destructive shell/git operations and sets both canonical and legacy strict env names for fail-closed compatibility.
- **Auto Update**: async SessionStart/SessionEnd update checks with lock/status files; older Claude versions use the legacy cache hook.
- **Status Line**: Python statusLine command showing model, context usage, and 5h/7d rate limits.
- **Doc Size Guard**: validates CLAUDE.md/AGENTS.md line counts and broken path references after Write.
- **Doc Size Guard**: non-blocking size-hygiene warning when CLAUDE.md/AGENTS.md exceeds line targets after Write.
- **Feature Recommendation**: writes pending feature names and notifies via SessionStart for enabled profiles.

## Platform Detection
Expand Down
12 changes: 6 additions & 6 deletions README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,11 @@ Other supported editors: [Cursor](https://www.cursor.com/) (AI-native), [Zed](ht

## Profiles

| Profile | Agents | Rules | Commands | Skills | Hooks | Memory | Plugins | Codex Plugin | Ghostty |
|---------|--------|-------|----------|--------|-------|--------|---------|-----------|---------|
| Minimal | Yes | Yes | - | - | - | - | - | - | - |
| Standard (Recommended) | Yes | Yes | Yes | Yes | Core | Yes | 5 | Optional | - |
| Full | Yes | Yes | Yes | Yes | All | Yes | 14 | Yes | macOS only |
| Profile | Agents | Rules | Commands | Skills | Hooks | Plugins | Codex Plugin | Ghostty |
|---|---|---|---|---|---|---|---|---|
| Minimal | Yes | Yes | - | - | - | - | - | - |
| Standard (Recommended) | Yes | Yes | Yes | Yes | Core | 5 | Optional | - |
| Full | Yes | Yes | Yes | Yes | All | 14 | Yes | macOS only |

- **Minimal**: Lightweight start with just agents and rules
- **Standard**: Best for most teams. Includes commands, skills, and core hooks
Expand Down Expand Up @@ -327,7 +327,7 @@ NONINTERACTIVE=1 bash -c "$(curl -fsSL https://raw.githubusercontent.com/cloudna
--new-init=true \
--codex-plugin=false \
--commit-attribution=false \
--hooks=safety-net,auto-update,tmux,prettier,pr-log,pre-commit \
--hooks=safety-net,auto-update,tmux,prettier,pr-log,pre-commit,agent-teams \
--plugins=security-guidance,commit-commands,pr-review-toolkit,document-skills@anthropic-agent-skills

# Reuse a saved config
Expand Down
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,6 @@ cd claude-code-starter-kit

> **エディタの質問について**: ステップ 5 で「どのエディタを使っていますか?」と聞かれます。
> これは使用しているエディタを記録するための設定です(現在この選択で挙動が変わる機能はありません)。
> エディタの起動や差分表示は行いません。「なし」を選ぶとこのフックは追加されません。
> **エディタをインストールしていない場合や、わからない場合は「5) なし」を選んでください。** Claude Code の動作には影響しません。
> エディタの詳細は「[エディタ(コードエディタ)とは?](#エディタコードエディタとは)」をご覧ください。

Expand Down Expand Up @@ -404,8 +403,7 @@ cd claude-code-starter-kit
| ルール(コーディング規約) | ✅ | ✅ | ✅ |
| コマンド(ショートカット) | - | ✅ | ✅ |
| スキル(専門知識) | - | ✅ | ✅ |
| フック(安全装置) | - | 主要(11個) | 全部(14個) |
| メモリ(記憶の永続化) | - | ✅ | ✅ |
| フック(安全装置) | - | 主要 | 全部 |
| プラグイン(拡張機能) | - | 5個 | 14個 |
| フォント(IBM Plex Mono / HackGen NF) | - | ✅ | ✅ |
| Codex Plugin(外部 AI 連携) | - | 任意 | ✅ |
Expand Down Expand Up @@ -462,7 +460,7 @@ URL・公式ドキュメント・ブログ・ニュース・OSS ページを読
- **セキュリティ**: SSRF 多層防御(http(s) 限定・内部/プライベート IP 拒否・接続 IP pin・リダイレクト各ホップ検査)、非フェッチ DOM(外部サブリソース取得・スクリプト実行なし)、PDF は CJK 対応・解凍爆弾対策付き。開発時のみ `ALLOW_PRIVATE_URLS=true` で内部 URL を許可。
- **依存の自動更新(opt-in)**: `web-content-update` フックが SessionStart でスキルの依存(defuddle/jsdom/pdfjs-dist)を更新(24h スロットル・テストゲート+ロールバック)。**Full のみ既定有効**、Standard では opt-in。手動更新は `npm run update:deps`。

### 🪝 フック(安全装置・15個
### 🪝 フック(安全装置・11個

フックは **自動で動作する安全装置** です。コードを書いたり保存したりしたときに、自動でチェックが走ります。

Expand Down Expand Up @@ -853,7 +851,7 @@ NONINTERACTIVE=1 bash -c "$(curl -fsSL https://raw.githubusercontent.com/cloudna
--codex-plugin=false \
--commit-attribution=false \
--ghostty=true \
--hooks=safety-net,auto-update,tmux,prettier,pr-log,pre-commit \
--hooks=safety-net,auto-update,tmux,prettier,pr-log,pre-commit,agent-teams \
--plugins=security-guidance,commit-commands,pr-review-toolkit,document-skills@anthropic-agent-skills
```

Expand Down
5 changes: 2 additions & 3 deletions docs/GUIDES/hooks-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,5 @@

## Compaction 前後の流れ(関連機能が有効な場合)

- `PreCompact`: compaction でコンテキストが要約される前に走る(例: pre-compact-commit のスナップショット)
- `PostCompact`: compaction 完了直後に走る
- `SessionStart`: 次セッション開始時の復元・通知に使う
- `PreCompact`: compaction でコンテキストが要約される前に走る(例: pre-compact-commit の stash スナップショット。opt-in)
- セッション状態の保存・復元はキットの hook では行わない — Claude Code ネイティブの auto-memory / checkpoint・rewind / --resume に委譲している
1 change: 1 addition & 0 deletions features/codex-plugin/CLAUDE.md.partial.en
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

---

# Codex Plugin
Expand Down
1 change: 1 addition & 0 deletions features/codex-plugin/CLAUDE.md.partial.ja
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

---

# Codex プラグイン
Expand Down
2 changes: 1 addition & 1 deletion features/doc-blocker/scripts/check-doc-write.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ _doc_blocker_slop_name() {
return "$matched"
}

if [[ "$file_path" =~ \.(md|txt)$ ]] && ! _doc_blocker_allowed_path "$file_path"; then
if [[ "$file_path" =~ \.([Mm][Dd]|[Tt][Xx][Tt])$ ]] && ! _doc_blocker_allowed_path "$file_path"; then
base="$(basename "$file_path")"
if _doc_blocker_slop_name "$base"; then
jq -cn --arg path "$file_path" '{
Expand Down
1 change: 0 additions & 1 deletion i18n/en/CLAUDE.md.base
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

## Basic Principles
- Follow the repository's existing commit style; use Conventional Commits format (feat: / fix: / refactor: / test: / docs: / chore:) when no convention exists

{{FEATURE:spec-kit}}
{{FEATURE:web-content-extraction}}
{{FEATURE:codex-plugin}}
Expand Down
1 change: 1 addition & 0 deletions i18n/en/partials/spec-kit.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@

## Optional: GitHub Spec Kit
- Run `/spec-kit-init` inside a project to bootstrap spec-driven development with GitHub Spec Kit (details, marker rules, and constitution precedence are documented in the command).
1 change: 1 addition & 0 deletions i18n/en/partials/web-content-extraction.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

## Web Fetch / URL Analysis

- When reading a web page, URL, official doc, blog post, news article, or OSS page, extract the main content with the `web-content-extraction` skill first (do not summarize or analyze raw HTML directly).
1 change: 1 addition & 0 deletions i18n/en/strings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ STR_HOOKS_BIOME="Biome Auto-format - Format and lint JS/TS files after edits"
STR_HOOKS_PR_LOG="PR Creation Log - Log PR URL after creation"
STR_HOOKS_PRE_COMMIT="Pre-compact Snapshot - Stash tracked changes before context compaction (opt-in)"
STR_HOOKS_DOC_SIZE="Doc Size Guard - Warn when CLAUDE.md/AGENTS.md is too large"
STR_HOOKS_AGENT_TEAMS="Agent Teams (experimental) - Enable Claude Code agent teams (CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS)"
STR_HOOKS_FEATURE_RECOMMENDATION="Feature Recommendation - Notify about new features on session start"

# web-content-extraction skill dependency install (deploy-time messages)
Expand Down
1 change: 0 additions & 1 deletion i18n/ja/CLAUDE.md.base
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

## 基本方針
- リポジトリに既存のコミット規約がある場合はそれに従い、ない場合は Conventional Commits 形式(feat: / fix: / refactor: / test: / docs: / chore:)を使う

{{FEATURE:spec-kit}}
{{FEATURE:web-content-extraction}}
{{FEATURE:codex-plugin}}
Expand Down
1 change: 1 addition & 0 deletions i18n/ja/partials/spec-kit.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@

## オプション: GitHub Spec Kit
- プロジェクト内で `/spec-kit-init` を実行すると GitHub Spec Kit による仕様駆動開発を導入できる(詳細・マーカー規則・constitution の優先順位はコマンド側に記載)。
1 change: 1 addition & 0 deletions i18n/ja/partials/web-content-extraction.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

## Web取得・URL解析

- Webページ・URL・公式Doc・ブログ・ニュース・OSSページを読むときは、`web-content-extraction` skill で本文を抽出してから読む(生HTMLをそのまま要約・分析しない)。
1 change: 1 addition & 0 deletions i18n/ja/strings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ STR_HOOKS_BIOME="Biome 自動フォーマット - JS/TS ファイルを編集後
STR_HOOKS_PR_LOG="PR 作成ログ - PR 作成後に URL をログ"
STR_HOOKS_PRE_COMMIT="コンパクト前スナップショット - compact 前に tracked 変更を git stash に退避(opt-in)"
STR_HOOKS_DOC_SIZE="ドキュメントサイズガード - CLAUDE.md/AGENTS.md の肥大化を警告"
STR_HOOKS_AGENT_TEAMS="Agent Teams(実験的) - Claude Code の agent teams を有効化(CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS)"
STR_HOOKS_FEATURE_RECOMMENDATION="機能レコメンド - セッション開始時に新機能を通知"

# web-content-extraction skill dependency install (deploy-time messages)
Expand Down
5 changes: 3 additions & 2 deletions lib/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -509,12 +509,13 @@ build_claude_md_to_file() {

cp -a "$base" "$out"

# Web content extraction standard rule — only when the skill is installed
# Spec Kit pointer — only when commands (incl. /spec-kit-init) are installed
if is_true "${INSTALL_COMMANDS:-false}"; then
local sk_partial="$PROJECT_DIR/i18n/${lang}/partials/spec-kit.md"
inject_feature "$out" "spec-kit" "$sk_partial"
fi

# Web content extraction standard rule — only when the skill is installed
if is_true "${INSTALL_SKILLS:-false}"; then
local wce_partial="$PROJECT_DIR/i18n/${lang}/partials/web-content-extraction.md"
inject_feature "$out" "web-content-extraction" "$wce_partial"
Expand All @@ -525,7 +526,7 @@ build_claude_md_to_file() {
inject_feature "$out" "codex-plugin" "$partial"
fi

remove_unresolved "$out"
remove_unresolved "$out" "delete"
}

# ---------------------------------------------------------------------------
Expand Down
8 changes: 5 additions & 3 deletions lib/update.sh
Original file line number Diff line number Diff line change
Expand Up @@ -550,18 +550,20 @@ _RETIRED_HOOK_FEATURES=(memory-persistence strategic-compact console-log-guard g

# _strip_retired_hook_entries - Remove hook commands referencing retired
# feature script dirs (~/.claude/hooks/<feature>/) from settings.json, then
# drop matchers/events left empty.
# drop matchers/events left empty. The pattern is anchored on "/.claude/" so
# a user script that merely lives under a directory named after a retired
# feature (e.g. ~/dotfiles/hooks/memory-persistence/) never matches.
_strip_retired_hook_entries() {
local settings_file="$1"
[[ -f "$settings_file" ]] || return 0
local feature tmp changed=false
for feature in "${_RETIRED_HOOK_FEATURES[@]}"; do
jq -e --arg p "/hooks/${feature}/" '
jq -e --arg p "/.claude/hooks/${feature}/" '
[(.hooks // {}) | to_entries[] | .value[]?.hooks[]? | (.command // "")]
| any(contains($p))
' "$settings_file" >/dev/null 2>&1 || continue
tmp="$(mktemp)"
if jq --arg p "/hooks/${feature}/" '
if jq --arg p "/.claude/hooks/${feature}/" '
if .hooks then
.hooks |= (to_entries
| map(.value |= (map((.hooks //= []) | .hooks |= map(select((.command // "") | contains($p) | not)))
Expand Down
2 changes: 1 addition & 1 deletion profiles/standard.conf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Standard profile: Recommended for most users
# Agents + Rules + Commands + Skills + Core hooks + Memory
# Agents + Rules + Commands + Skills + Core hooks

ENABLE_NEW_INIT=true

Expand Down
41 changes: 41 additions & 0 deletions tests/unit/test-merge.sh
Original file line number Diff line number Diff line change
Expand Up @@ -762,3 +762,44 @@ _write_json() {
rm -f "$snapshot" "$current" "$new_kit" "$output"
unset _prev_interactive
}

# ---------------------------------------------------------------------------
# effortLevel pin removal (#120/#138): kit-removed key is deleted for
# unchanged users and preserved for users who overrode it
# ---------------------------------------------------------------------------
{
test_name="3way: kit-removed effortLevel is deleted when user never changed it"
snapshot="$(_write_json '{"effortLevel": "high", "language": "en"}')"
current="$(_write_json '{"effortLevel": "high", "language": "en"}')"
new_kit="$(_write_json '{"language": "en"}')"
output="$(mktemp)"

run_func merge_settings_3way "$snapshot" "$current" "$new_kit" "$output"

if [[ "$_RF_RC" -eq 0 ]] \
&& [[ "$(jq 'has("effortLevel")' "$output")" == "false" ]] \
&& assert_json_field "$output" '.language' "en"; then
pass "$test_name"
else
fail "$test_name"
fi
rm -f "$snapshot" "$current" "$new_kit" "$output"
}

{
test_name="3way: kit-removed effortLevel is preserved when user overrode it"
snapshot="$(_write_json '{"effortLevel": "high", "language": "en"}')"
current="$(_write_json '{"effortLevel": "max", "language": "en"}')"
new_kit="$(_write_json '{"language": "en"}')"
output="$(mktemp)"

run_func merge_settings_3way "$snapshot" "$current" "$new_kit" "$output"

if [[ "$_RF_RC" -eq 0 ]] \
&& assert_json_field "$output" '.effortLevel' "max"; then
pass "$test_name"
else
fail "$test_name"
fi
rm -f "$snapshot" "$current" "$new_kit" "$output"
}
45 changes: 45 additions & 0 deletions tests/unit/test-retired-hooks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,51 @@ _rh_run() {
'
}

{
test_name="retired-hooks: all retired feature entries are stripped in one pass"
_rh_all="$_rh_tmp/all-retired.json"
cat > "$_rh_all" <<'JSON'
{
"hooks": {
"PreToolUse": [
{"matcher": "*", "hooks": [
{"type": "command", "command": "/home/u/.claude/hooks/strategic-compact/suggest-compact.sh"},
{"type": "command", "command": "/home/u/.claude/hooks/git-push-review/remind.sh"}
]}
],
"PostToolUse": [
{"matcher": "Edit|Write", "hooks": [
{"type": "command", "command": "/home/u/.claude/hooks/console-log-guard/check-file.sh"}
]}
],
"SessionStart": [
{"matcher": "*", "hooks": [
{"type": "command", "command": "/home/u/.claude/hooks/memory-persistence/session-start.sh"}
]}
]
}
}
JSON
_rh_run "$_rh_all" >/dev/null 2>&1
if [[ "$(jq -r '.hooks | length' "$_rh_all")" == "0" ]]; then
pass "$test_name"
else
fail "$test_name"
fi
}

{
test_name="retired-hooks: user script under a same-named dir outside ~/.claude is kept"
_rh_user="$_rh_tmp/user-dir.json"
printf '{"hooks":{"PreCompact":[{"matcher":"*","hooks":[{"type":"command","command":"/home/u/dotfiles/hooks/memory-persistence/mine.sh"}]}]}}\n' > "$_rh_user"
_rh_run "$_rh_user" >/dev/null 2>&1
if [[ "$(jq -r '.hooks.PreCompact[0].hooks | length' "$_rh_user")" == "1" ]]; then
pass "$test_name"
else
fail "$test_name"
fi
}

{
test_name="retired-hooks: memory-persistence entries are stripped, others kept"
_rh_settings="$_rh_tmp/settings.json"
Expand Down
Loading
Loading