Skip to content

chore: 共有Claude設定を全CLAUDE_CONFIG_DIRへ同期する - #977

Merged
keito4 merged 1 commit into
mainfrom
chore/sync-claude-settings-to-all-config-dirs
Jul 15, 2026
Merged

chore: 共有Claude設定を全CLAUDE_CONFIG_DIRへ同期する#977
keito4 merged 1 commit into
mainfrom
chore/sync-claude-settings-to-all-config-dirs

Conversation

@keito4

@keito4 keito4 commented Jul 15, 2026

Copy link
Copy Markdown
Owner

Closes #976

背景

settings.jsonCLAUDE_CONFIG_DIR ごとに独立しており、~/.claude の hooks / permissions / plugins は他の config dir では一切読まれない。Agent Deck が group ごとに config dir を振り分けている(common/n8n/private → ~/.claude-private、elu → ~/.claude-elu)ため、大半のセッションで Quality Gates も permissions の deny も attribution も効いていなかった

実測(2026-07-15・メインMac):

~/.claude          hooks=29
~/.claude-private  hooks=1   ← model のみ
~/.claude-elu      hooks=0   ← theme/tui のみ

変更内容

script/setup-claude.shsync_settings_to_extra_config_dirs() を追加し、main() の設定セットアップ直後に実行する。

  • ~/.claude/settings.json共有キーのみを他の config dir へマージ
    • 共有:$schema / hooks / permissions / enabledPlugins / extraKnownMarketplaces / attribution
    • 保持:model / theme / tui 等の dir 固有キーはそのまま
  • 対象 dir は ~/.claude-* を自動検出(CLAUDE_EXTRA_CONFIG_DIRS で明示指定も可)
  • 冪等:差分がなければ書き込まない
  • 安全側:既存ファイルが不正JSONなら上書きせずスキップ。jq 不在・正本不在は警告のみで続行
  • DevContainer は対象 dir が存在しないため no-op

手動コピーではなく配布スクリプトに寄せているのは、2系統に分かれた設定が必ずドリフトするため。

検証

隔離した偽 HOME で実施:

  • 共有キーが private/elu に入り、model(opus[1m])・theme(light)・tui(fullscreen)は保持されることを確認
  • 2回目の実行で「最新です」となり書き込みが発生しないこと(冪等)を確認
  • 対象ファイルを not json に壊した状態で実行し、上書きされずスキップされることを確認
  • shellcheck -S warning クリーン(exit 0)

メインMacへの適用も実施済みで、3 dir すべてが hooks=29 / permissions.deny あり / attribution あり になることを実機で確認。SessionStart の人生システムメモリ注入フックが維持されることも確認済み。

レビュー観点

  • 共有キーの選定(model を共有に含めるべきか。現状 ~/.claude-elu は model 未設定のまま)
  • agent-deck / StreamDeck 連携フックも一律配布しているが、private/elu で二重発火などの副作用がないか

Summary by CodeRabbit

  • New Features
    • Added automatic synchronization of selected Claude settings—such as model, theme, and TUI preferences—across additional configuration directories.
    • Preserves directory-specific settings by merging only approved shared preferences.
    • Safely skips synchronization when configuration files are unavailable, invalid, or cannot be processed.

settings.json は CLAUDE_CONFIG_DIR ごとに独立しており、~/.claude の
hooks / permissions / plugins は他の config dir では一切読まれない。

Agent Deck は config.toml の [groups.*.claude] config_dir により
common/n8n/private を ~/.claude-private、elu を ~/.claude-elu に
振り分けるため、大半のセッションが ~/.claude の設定を受け取れていない。

2026-07-15 時点の実測:
  ~/.claude          hooks=29 (permissions/plugins/attribution あり)
  ~/.claude-private  hooks=1  (model のみ)
  ~/.claude-elu      hooks=0  (theme/tui のみ)

結果として private/elu セッションでは
  - Quality Gates と --no-verify ブロックが効かない
  - permissions の deny が未適用
  - attribution 設定(帰属表記の抑止)が未適用
  - プラグインが読まれない
状態になっていた。

setup-claude.sh に sync_settings_to_extra_config_dirs を追加し、
~/.claude/settings.json の共有キー($schema/hooks/permissions/
enabledPlugins/extraKnownMarketplaces/attribution)のみを他の
config dir へマージする。model/theme/tui 等の dir 固有キーは保持。

- 対象 dir は ~/.claude-* を自動検出(CLAUDE_EXTRA_CONFIG_DIRS で上書き可)
- 冪等。差分がなければ書き込まない
- 不正JSONの既存ファイルは上書きせずスキップ
- jq 不在時・正本不在時は警告のみで続行(DevContainer は対象dirが無く no-op)
@cursor

cursor Bot commented Jul 15, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@claude

claude Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Claude finished @keito4's task in 0s —— View job


I'll analyze this and get back to you.

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The Claude setup script now discovers additional configuration directories and synchronizes allowlisted settings from the primary configuration, preserving directory-specific values and skipping invalid or unavailable targets.

Changes

Claude settings synchronization

Layer / File(s) Summary
Discover and merge shared settings
script/setup-claude.sh
Defines the primary settings path and shared-key allowlist, discovers extra configuration directories, validates JSON, and conditionally merges changed settings.
Invoke synchronization during setup
script/setup-claude.sh
Calls synchronization after settings.local.json setup and before the remaining Claude installation flow.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SetupScript
  participant PrimarySettings
  participant ExtraConfigDirs
  participant jq
  SetupScript->>PrimarySettings: read primary settings.json
  SetupScript->>ExtraConfigDirs: discover configured or ~/.claude-* directories
  SetupScript->>jq: validate and merge allowlisted keys
  jq-->>SetupScript: merged target JSON
  SetupScript->>ExtraConfigDirs: write changed settings.json files
Loading

Possibly related PRs

  • keito4/config#303: Updates the settings.local.json setup flow that this change extends with settings synchronization.

Suggested labels: size/M

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes syncing shared Claude settings across CLAUDE_CONFIG_DIRs.
Description check ✅ Passed The description covers the motivation, changes, verification, and related issue, even if it doesn't follow the template headings exactly.
Linked Issues check ✅ Passed The changes satisfy #976 by syncing shared settings, preserving dir-specific keys, skipping invalid JSON, and no-oping when no target dirs exist.
Out of Scope Changes check ✅ Passed The PR stays focused on the requested Claude settings sync and does not introduce unrelated scope.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/sync-claude-settings-to-all-config-dirs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0533aeb26f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread script/setup-claude.sh
# 複数の CLAUDE_CONFIG_DIR に共有設定を配るためのキー。
# ここに無いキー(model / theme / tui 等)は各 dir 固有として保持される。
# shellcheck disable=SC2016 # jq に渡すJSONリテラル。$schema はシェル変数ではない
CLAUDE_SHARED_SETTINGS_KEYS='["$schema","hooks","permissions","enabledPlugins","extraKnownMarketplaces","attribution"]'

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 Install plugins for each synced config dir

When setup is run from the normal shell, this copies enabledPlugins/extraKnownMarketplaces into ~/.claude-*, but the later claude plugin install flow still runs only for the active Claude config and never installs plugin artifacts under those target dirs. I checked the Claude Code docs: CLAUDE_CONFIG_DIR stores plugins under that path, and enabledPlugins does not by itself install external plugins. As a result, Agent Deck sessions using CLAUDE_CONFIG_DIR=~/.claude-private can get settings that claim plugins are enabled while the plugin commands/hooks/LSPs remain absent until a separate per-dir install is run.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@script/setup-claude.sh`:
- Around line 96-98: Update the directory-processing loop around target_dir so
each non-empty path with a leading "~/” is expanded to use $HOME before
constructing target_file, while preserving absolute and other explicit paths
unchanged.
- Around line 151-154: Move the sync_settings_to_extra_config_dirs invocation
and its preceding log_info from the current position to the end of main(),
immediately before the final log_success message. Keep synchronization after all
canonical settings updates, including plugins::sync_repo_content and
plugins::apply_hookify_patch.
- Around line 123-124: Update the copy flow surrounding cp and log_success so it
checks the cp exit status before reporting success. On failure, handle the copy
error explicitly according to the script’s existing error-handling conventions,
and only call log_success after the copy completes successfully.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7c3bf0f5-2836-499a-801d-39318d58778c

📥 Commits

Reviewing files that changed from the base of the PR and between b0d7755 and 0533aeb.

📒 Files selected for processing (1)
  • script/setup-claude.sh

Comment thread script/setup-claude.sh
Comment on lines +96 to +98
while IFS= read -r target_dir; do
[[ -n "$target_dir" ]] || continue
target_file="${target_dir}/settings.json"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Expand tildes in explicit directory paths.

If a user specifies paths starting with ~/ in CLAUDE_EXTRA_CONFIG_DIRS (e.g., passing it in quotes), bash will not automatically perform tilde expansion when reading the variable. This will result in a literal directory named ~ being created in the current working directory. You can use parameter expansion to safely replace a leading tilde with the $HOME path.

💡 Proposed fix
     while IFS= read -r target_dir; do
         [[ -n "$target_dir" ]] || continue
+
+        # Handle tilde expansion for explicitly provided paths
+        if [[ "$target_dir" == "~" ]] || [[ "$target_dir" == "~/"* ]]; then
+            target_dir="${target_dir/#\~/$HOME}"
+        fi
+
         target_file="${target_dir}/settings.json"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
while IFS= read -r target_dir; do
[[ -n "$target_dir" ]] || continue
target_file="${target_dir}/settings.json"
while IFS= read -r target_dir; do
[[ -n "$target_dir" ]] || continue
# Handle tilde expansion for explicitly provided paths
if [[ "$target_dir" == "~" ]] || [[ "$target_dir" == "~/"* ]]; then
target_dir="${target_dir/#\~/$HOME}"
fi
target_file="${target_dir}/settings.json"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@script/setup-claude.sh` around lines 96 - 98, Update the directory-processing
loop around target_dir so each non-empty path with a leading "~/” is expanded to
use $HOME before constructing target_file, while preserving absolute and other
explicit paths unchanged.

Comment thread script/setup-claude.sh
Comment on lines +123 to +124
cp "$merged_file" "$target_file"
log_success " ${target_dir} に共有設定を同期しました"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Verify the exit status of cp to ensure accurate logging.

If the cp command fails (e.g., due to file permission issues or lack of disk space), the script will incorrectly log a success message. Additionally, if the script is executed in an environment with set -e, an unhandled command failure will unexpectedly terminate the setup process.

🛡️ Proposed fix to handle copy failures
-                cp "$merged_file" "$target_file"
-                log_success "  ${target_dir} に共有設定を同期しました"
+                if cp "$merged_file" "$target_file"; then
+                    log_success "  ${target_dir} に共有設定を同期しました"
+                else
+                    log_warn "  ${target_dir} への共有設定の同期に失敗しました"
+                fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
cp "$merged_file" "$target_file"
log_success " ${target_dir} に共有設定を同期しました"
if cp "$merged_file" "$target_file"; then
log_success " ${target_dir} に共有設定を同期しました"
else
log_warn " ${target_dir} への共有設定の同期に失敗しました"
fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@script/setup-claude.sh` around lines 123 - 124, Update the copy flow
surrounding cp and log_success so it checks the cp exit status before reporting
success. On failure, handle the copy error explicitly according to the script’s
existing error-handling conventions, and only call log_success after the copy
completes successfully.

Comment thread script/setup-claude.sh
Comment on lines +151 to +154
# 追加の CLAUDE_CONFIG_DIR(~/.claude-private 等)へ共有設定を同期
log_info "追加の CLAUDE_CONFIG_DIR に共有設定を同期します..."
sync_settings_to_extra_config_dirs

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Execute synchronization after the canonical settings.json is fully updated.

Running sync_settings_to_extra_config_dirs at this stage causes it to sync the stale version of settings.json. If subsequent setup steps—such as plugins::sync_repo_content (which copies the latest repo configuration to $CLAUDE_DIR) or plugins::apply_hookify_patch—update the canonical settings, those updates will not reach the extra directories until the user runs the setup script a second time.

Remove these lines from their current position and place them at the very end of the main() function, immediately before the final log_success message, to ensure the most up-to-date canonical settings are always distributed.

✂️ Remove from here
-    # 追加の CLAUDE_CONFIG_DIR(~/.claude-private 等)へ共有設定を同期
-    log_info "追加の CLAUDE_CONFIG_DIR に共有設定を同期します..."
-    sync_settings_to_extra_config_dirs
-
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@script/setup-claude.sh` around lines 151 - 154, Move the
sync_settings_to_extra_config_dirs invocation and its preceding log_info from
the current position to the end of main(), immediately before the final
log_success message. Keep synchronization after all canonical settings updates,
including plugins::sync_repo_content and plugins::apply_hookify_patch.

@keito4
keito4 merged commit 6170b5b into main Jul 15, 2026
25 checks passed
@keito4
keito4 deleted the chore/sync-claude-settings-to-all-config-dirs branch July 15, 2026 09:08
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 1.123.4 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

@github-actions github-actions Bot added the released リリース済み label Jul 15, 2026
keito4 added a commit that referenced this pull request Jul 15, 2026
Agent Deck の group ごとに CLAUDE_CONFIG_DIR が切り替わるが、~/.claude 以外
の dir には commands / agents / skills が1件も無く、private セッションでは
/session-close を含む全コマンドが使えなかった。

正本はリポジトリではなく ~/.claude とする。keito4/config は public のため
個人の Notion ID を含むコマンドは追跡できない。#977 の settings.json 同期と
同じ思想で、~/.claude を正本に他の dir へ配る。

コピーではなくシンボリックリンクにした。dir 固有の差分を持つ理由が現状なく、
コピーは make claude-setup を忘れた端末で静かにドリフトするため。
hooks は settings.json 側がプロジェクト相対で解決するので対象外。

実体ディレクトリがある場合は中身を失うため触らず警告する。

テストは偽 HOME で実際にスクリプトを起動し、リンクが張られたことを実体で
検証する(実装を外すと 4 件が赤になることを確認済み)。

Closes #981

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

released リリース済み

Projects

None yet

Development

Successfully merging this pull request may close these issues.

~/.claude 以外の CLAUDE_CONFIG_DIR に hooks・permissions・plugins が配布されていない

1 participant