settings.local.jsonがgitignoreなしで除外される仕組み — Claude Code
settings.local.jsonは初回書き込み時にグローバルgit excludesへ自動追記され、gitignore編集なしで除外されます。手動作成や追跡済みの例外と、Claudeに読ませないファイルの指定も示します。
.claude/settings.local.json はプロジェクトごとの個人設定を置くファイルですが、.gitignore に自分で書かなくてもコミット対象から外れます。Claude Codeが初めてこのファイルへ書き込むとき、グローバルなgit excludesファイルへパターンを自動追記するためです。
守られるのは「Claude Codeが書いた場合」だけです。手で作った直後はこの保護が働きません。すでにgitが追跡しているファイルには、除外パターンがあっても効きません。
settings.local.jsonがgitignore不要で除外される理由
Claude Codeは、Bashコマンドの許可プロンプトで「Yes, and don't ask again」を選ぶと、その承認を allow ルールとして .claude/settings.local.json に保存します。/config の一部の項目(Show tipsなど)も、ユーザー設定ではなくこのファイルに保存されます。選択肢ごとの保存内容は許可プロンプトで何が保存されるかにまとめています。
書き込みが初めて発生したとき、そのgitリポジトリがまだこのファイルを無視していなければ、Claude Codeは **/.claude/settings.local.json をグローバルgit excludesファイルに追記します。パターンの先頭が **/ なので、そのマシン上のどのリポジトリでも同じ場所のファイルが除外されます。プロジェクトの .gitignore は一度も編集されません。
流れを順に並べると、次のとおりです。
自動で除外されるまで
- 1
許可プロンプトで承認を保存する
Bashコマンドの許可プロンプトで「Yes, and don't ask again」を選びます。
- 2
Claude Codeがファイルへ初めて書き込む
リポジトリがこのファイルをまだ無視していない場合に限り、次の手順へ進みます。
- 3
グローバルgit excludesへパターンが追記される
**/.claude/settings.local.jsonが1行足され、ファイルはgit statusの対象から外れます。
.claude/settings.json は「コミットすればチーム全員に届く」設定です。.claude/settings.local.json はその上に重なる「自分のこの1プロジェクトだけ」のスコープで、同じキーはlocal側が勝ちます。たとえばチームのファイルが "model": "claude-sonnet-5" でも、localに別のモデルを書けば自分のセッションだけが変わります。スコープの全体像はClaude Code settings.json完全ガイドにあります。
個人の上書きとして書くのは、たとえば次のような短いファイルです。Show tipsを切る spinnerTipsEnabled: false をこのファイルに書くと、そのプロジェクトの自分のセッションだけでヒント表示が止まり、チームメイトの表示は変わりません。
{
"spinnerTipsEnabled": false
}なお ~/.claude/settings.local.json は、ホームディレクトリそのもので始めたセッションでだけ読まれます。全プロジェクトに効かせたい許可ルールは、ユーザー設定の ~/.claude/settings.json に書きます。
グローバルgit excludesへの追記先はどこか
追記先は個人のgit設定で決まります。分かれ目は、core.excludesFile が絶対パスか ~ から始まるパスで設定されているかどうかです。
| git設定の状態 | 追記先 |
|---|---|
core.excludesFile を絶対パスまたは ~/... で設定済み | 追記先そのファイル |
上記以外で XDG_CONFIG_HOME が設定済み | 追記先$XDG_CONFIG_HOME/git/ignore |
上記以外で XDG_CONFIG_HOME が未設定 | 追記先~/.config/git/ignore |
相対パスで core.excludesFile を書いている人は、1行目に当てはまらないので注意が要ります。追記先が ~/.config/git/ignore や $XDG_CONFIG_HOME/git/ignore になり、自分が見ているファイルに行が増えません。
手作りしたファイルは守られない — gitの出力で確かめる
公式の記述は、手で作ったファイルについて「Claude Codeがまだ書き込んでいないなら、自分で .gitignore に追加する」というものです。この境目を、使い捨てのリポジトリでgit(2.50.1)だけを動かして見てみます。Claude Codeは起動せず、HOME と GIT_CONFIG_GLOBAL を一時ディレクトリに向けています。
git init -q && mkdir .claude && echo '{}' > .claude/settings.local.json
git check-ignore -v .claude/settings.local.json; echo "exit=$?"
git status --shortexit=1
?? .claude/どのパターンにも一致しないと check-ignore は何も出力せず、終了コード1を返します。git status では .claude/ が未追跡として出ているので、git add . で入ってしまう状態です。そこへ既定の追記先にパターンを置くと、状況が変わります。
mkdir -p ~/.config/git && echo '**/.claude/settings.local.json' > ~/.config/git/ignore
git check-ignore -v .claude/settings.local.json; echo "exit=$?"~/.config/git/ignore:1:**/.claude/settings.local.json .claude/settings.local.json
exit=0出力は「ファイル:行番号:パターン」の順に並びます。このファイルが ~/.config/git/ignore の1行目で除外されている、という意味です。実機では先頭の ~ が展開され、絶対パスで表示されます(以下の出力も同様です)。core.excludesFile を設定してそのファイルに同じ行を置いても、-v の1項目目が置いたファイルのパスに変わるだけで除外されます。
つまずきやすいのは、次の2つの場面です。
- テンプレートから雛形をコピーした場合: Claude Codeがまだ書いていないため、自動追記は起きません。コピーした時点で
.gitignoreに追加します。 - 導入前に誰かが手で作っていた場合: 最初の許可プロンプトより先にファイルがあっても、書き込みが起きるまではリポジトリは無視していません。
手で作った直後や既存プロジェクトへの導入直後は、git check-ignore -v を先に走らせれば安全です。何も出なければ、除外はまだ働いていません。
すでに追跡されたファイルには除外が効かない
除外パターンが効くのは、gitがまだ追跡していないファイルだけです。同じ一時リポジトリで、ファイルを一度 git add -f してインデックスに載せると、次のようになります。
git add -f .claude/settings.local.json
git check-ignore -v .claude/settings.local.json; echo "exit=$?"
git check-ignore -v --no-index .claude/settings.local.json
git status --shortexit=1
~/.config/git/ignore:1:**/.claude/settings.local.json .claude/settings.local.json
A .claude/settings.local.json通常の check-ignore は何も返さず、git status にはステージ済みの A が出ます。--no-index を付けるとパターンの一致そのものは見えるので、パターンは正しく置かれたまま、追跡済みだから効いていないと読み分けられます。誤ってコミットしたあとで除外を足しても、すでに追跡されたファイルはそのままです。追跡から外すには git rm --cached .claude/settings.local.json を使います。
この違いは見た目の問題にとどまりません。次の節で扱うように、追跡済みかどうかはClaude Codeが許可ルールをどう扱うかにも直結します。
worktreeとリポジトリルートでの配置ルール
Claude Codeは、セッションを開始したディレクトリではなくgitリポジトリのルートでこのファイルを読み書きします。サブディレクトリで始めても、承認はリポジトリ全体に適用されます。worktreeでは、worktreeごとのルートではなくメインチェックアウトのルートのファイルを使います。
ルートに集約されない場合は、.claude/settings.json と同じ場所に置かれます。
local設定の置き場所
リポジトリルート
gitリポジトリの中なら、サブディレクトリやworktreeで始めても、ここ(worktreeではメインチェックアウトのルート)のファイルを使います。
.claude/settings.json と同じ場所
リポジトリの外、リポジトリルートがホームディレクトリ、Windows、あるいはルート・.git・.claude が自分のユーザー所有でないときです。
パーミッションルールの中で / から始まるパスや、相対的なサンドボックスのパスは、リポジトリルートではなくセッションの作業ディレクトリが基準です。ルート集約とは別の規則なので、混同しやすい点です。
v2.1.211より前は、セッションを始めたディレクトリにファイルを置いていました。いまのバージョンでも、旧位置に残ったファイルは読み込まれます。同じキーを両方が設定していれば、リポジトリルート側の値が優先され、パーミッションルールは両方のファイルから適用されます。Agent SDKの resolveSettings() だけは、常に開始ディレクトリのファイルを読みます。
追跡済みになるとworkspace trustの扱いが変わる
.claude/settings.local.json は自分のファイルなので、Claude Codeはその allow ルールを、コミット済みの .claude/settings.json に必要なworkspace trustのステップなしで適用します。ただし、ファイルがgitで追跡されているか、.claude ディレクトリ自体がシンボリックリンクのときは別です。
local設定のallowルールの扱い
未追跡のまま
自分のファイルとして扱われ、allow ルールは信頼ダイアログを待たずに適用されます。
gitが追跡している
リポジトリ側のファイルとして扱われ、フォルダを信頼するまで allow ルールは保留されます。
追跡かどうかの判定にはgitが使われ、実行されるのはフォルダを信頼したあとです。ダイアログを承諾済みの場合に加え、-p やSDKのセッションは承諾済みとして数えられます。
信頼前の扱いは、セッションを始めた場所で決まります。ホームディレクトリ、または CLAUDE_CONFIG_DIR に指定した .claude ディレクトリの親で始めたときは、gitを実行せずそのフォルダのlocalファイルを適用します。それ以外の場所では、プロジェクト設定と同じくルールを保留します。判定が済んだあとは、未追跡のファイルや、gitリポジトリの外にあるフォルダのファイルのルールが、そのフォルダを信頼していなくても適用されます。
CLAUDE_CONFIG_DIR の親ディレクトリがgitリポジトリの中にあり、localファイルがリポジトリルートに置かれる場合は、この例外が効かず、ほかの場所と同じく保留されます。
「保存したはずの許可ルールが効かない」ときは、まず git ls-files .claude/settings.local.json で追跡されていないかを見ます。何か出力されたら、追跡済みなので保留の対象です。許可プロンプトが繰り返し出る原因の全体像はClaude Code権限モデルの変遷で扱っています。
Claude Codeに読ませたくないファイルは.gitignoreでは除外できない
「Claude Codeにファイルを無視させたい」場合、.gitignore や .claudeignore は主役になりません。.gitignore は、Claude Codeの読み取りを禁止する仕組みではありません。.claudeignore というファイルは、置いても効果がありません。
読み書きを止めたいファイルは、permissions.deny に Read ルールで書きます。パターンの書式はgitignoreと同じです。
{
"permissions": {
"deny": ["Read(./.env)", "Read(./secrets/**)"]
}
}Read の拒否ルールは、同じパスへのEditとWriteも止めます。波及するのはEditがv2.1.208以降、Writeがv2.1.228以降です。NotebookEditは対象外なので、止めたいなら Edit の拒否ルールを別に書きます。止まったときの症状はRead deny ruleエラーの切り分けで扱っています。
このルールはGrepやGlob、@ でのファイル参照にも適用されますが、効き方はbest-effortです。Bashで cat や sed を使う場合も、コマンドが認識できる範囲で対象になります。grep -r のようにファイル名を指定せず読むコマンドや、スクリプト経由の読み取りは対象外です。OSレベルで止めたいときはサンドボックスを使います。
.gitignore に関係する主な設定は respectGitignore です。これは @ のファイル選択画面に、gitignore済みのファイルを出さないかどうかを決めるもので、読み取りの禁止ではありません。GrepやGlobでの挙動の違いはrespectGitignoreの詳細が扱っています。
この拒否ルールは、チームで共有する .claude/settings.json に書いても、個人用の .claude/settings.local.json に書いても動きます。個人のローカルな除外なら、この記事で扱ってきたlocalファイルが置き場所です。
チームに配るときの判断
誤コミットが問題になるのは、ファイルの中身のためです。allow ルールにはコマンドのプレフィックスやファイルパスのパターンが並ぶので、社内ツールの名前やローカルの絶対パスが共有リポジトリに残ることがあります。履歴に入った分は git rm --cached で外しても消えないので、扱いはチームで決めることになります。
雛形のコピーで配る手順があるなら、コピー先の .gitignore への追記も同じ手順に入れておくと、自動追記が働かない経路でも誤コミットを避けられます。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。