
왜 .claude/settings.local.json은 Git 관리 대상에 포함해서는 안 되는가
요약
Claude Code 사용 시 생성되는 `.claude/settings.local.json` 파일을 Git 관리 대상에서 제외해야 하는 이유를 설명합니다. 이 파일을 커밋할 경우 워크스페이스 신뢰 메커니즘으로 인해 로컬 설정이 의도치 않게 작동하지 않을 수 있습니다.
핵심 포인트
- .claude/settings.local.json은 개인 로컬 설정 파일이므로 Git에 포함해서는 안 됩니다.
- 파일을 커밋하면 Claude Code의 워크스페이스 신뢰 메커니즘에 의해 설정이 무시될 수 있습니다.
- 보안을 위해 리포지토리 유래 파일과 사용자 로컬 파일을 구분하는 사양 때문입니다.
- 자동 제외가 작동하지 않을 경우 직접 .gitignore에 추가해야 합니다.
Claude Code를 사용하다 보면, .claude/settings.local.json이라는 파일이 늘어갑니다.
명령어 실행 시 확인 다이얼로그에서 「Yes, and don't ask again」을 선택할 때마다, 허가 규칙이 자동으로 추가되는 파일입니다.
이 파일은 Git의 추적 대상(tracking target)에 포함해서는 안 됩니다. 이름 그대로 「각자의 로컬 환경에 고유한 설정」이기 때문입니다.
하지만 평소에는 별로 의식하지 못할 것입니다.
Claude Code 스스로가 이 파일에 설정을 저장할 때, 리포지토리(repository)가 아직 무시하고 있지 않다면, 글로벌 git excludes 파일에 **/.claude/settings.local.json을 자동으로 추가해 줍니다.
제외 대상은 글로벌 git 설정의 core.excludesFile이 절대 경로 또는 ~로 시작하도록 지정되어 있으면 해당 파일이며, 그렇지 않으면 $XDG_CONFIG_HOME/git/ignore 또는 ~/.config/git/ignore가 됩니다.
문제가 되는 것은 이 자동 처리가 작동하지 않는 경우입니다.
- 수동으로 파일을 만든 경우
- Claude에게 Write 툴로 쓰게 한 경우
- 기존 리포지토리를 인계받았는데, 왠지 모르게 추적 대상에 포함되어 있었던 경우
공식 문서에서도 이러한 경우에는 직접 gitignore에 추가하도록 명시하고 있습니다.
그렇다면 추적 대상에 포함되어 있으면 구체적으로 어떤 일이 벌어지는가. 이 기사에서는 두 가지 이유로 정리하여 해설합니다.
Claude Code의 권한 설정 파일은 용도에 따라 나누어져 있습니다.
| 파일 | 상정 용도 | Git |
|---|---|---|
.claude/settings.json | 팀에서 공유하는 설정 | 커밋(commit)한다 |
.claude/settings.local.json | 자신만의 설정 | 커밋하지 않는다 |
settings.local.json은 사람이 직접 작성한다기보다, 확인 다이얼로그에서의 승인 조작 결과로서 Claude Code가 자동 생성 및 자동 추가해 나가는 파일입니다.
{
"permissions": {
"allow": [
...
언뜻 보면 「이것을 커밋하면 팀원 전원에게 배포할 수 있지 않을까?」라고 생각될 수 있습니다. 하지만 그렇게 하면 다음 두 가지 문제가 발생합니다.
Claude Code에는 **워크스페이스 신뢰 (workspace trust)**라는 메커니즘이 있습니다.
프로젝트의 .claude/settings.json에 작성된 permissions.allow (허가 규칙)와 permissions.additionalDirectories (작업 대상으로 추가할 디렉토리)는 권한을 부여하는 설정이므로, 실행 시 표시되는 「이 폴더를 신뢰합니까?」라는 다이얼로그를 승낙할 때까지 적용되지 않습니다. 규칙 자체는 읽어오지만, 실제로는 사용되지 않는 상태가 됩니다.
이는 악의적인 리포지토리를 clone 하는 것만으로 「위험한 명령어를 확인 없이 실행해도 좋다」라는 설정이 자동으로 활성화되는 것을 방지하기 위한 사양입니다.
settings.local.json은 본래 당신 자신의 파일이므로, 통상적으로 이 신뢰 체크는 적용되지 않습니다. 그런데 Git에 커밋되어 있으면 「리포지토리가 공급할 수 있는 파일」이라고 판정되어, 프로젝트 설정과 마찬가지로 신뢰 체크의 대상이 됩니다. .claude가 심볼릭 링크(symbolic link)인 경우도 마찬가지입니다.
Claude Code 입장에서는 「당신이 직접 커밋한 것인지」 「타인의 리포지토리에 처음부터 심어져 있었던 것인지」를 구별할 수 없습니다. git을 실행하여 해당 파일이 리포지토리 유래인지 확인할 뿐이므로, 안전한 쪽으로 치우친 판정을 내리게 됩니다.
이 부분은 오해하기 쉬운 포인트이므로 보충하겠습니다.
Claude Code가 이 git 체크를 실행하는 것은, 신뢰 다이얼로그를 이미 승낙한 폴더(또는 그 상위 폴더)에 한정됩니다. 따라서 아직 신뢰하지 않는 폴더에서의 대화 세션에서는, 추적 대상 외의 settings.local.json이라 하더라도 allow 규칙과 additionalDirectories는 프로젝트 설정과 마찬가지로 신뢰 체크를 거치며, 다이얼로그를 승낙할 때까지 적용되지 않습니다.
예외는 두 가지입니다.
- 자신의 설정 홈(Settings Home)에서 세션을 실행하는 경우 (홈 디렉터리 또는
CLAUDE_CONFIG_DIR로 지정한 디렉터리)… git 체크를 실행할 필요가 없으므로, 다이얼로그 승낙 전부터 적용됩니다. - 기동 디렉터리가 git 리포지토리 외부에 있는 경우… 단, "리포지토리 외부임"을 판정하는 데에도 동일한 git 체크를 사용하기 때문에, 이 경우는 다이얼로그 승낙 후에 효력이 발생합니다.
"추적 대상에서 제외하면 무조건 즉시 유효해진다"는 것은 v2.1.207 이전의 동작입니다.
현행 버전에서는, 승낙된 폴더에서 추적 대상인지 여부에 따라 차이가 발생한다고 이해하는 것이 정확합니다.
deny 규칙(금지 규칙)과 ask 규칙(매번 확인하는 규칙)은 제한을 가할 뿐이므로, 신뢰 체크의 영향을 받지 않습니다.
허가(allow)만이 심사 대상이 되고, 금지(deny)는 항상 유지된다는 비대칭적인 동작이 됩니다.
Bash나 PowerShell의 커맨드 승인은 리포지토리 단위·커맨드 단위로 영구적으로 저장됩니다. 즉, 승인할 때마다 파일이 새로 써집니다.
게다가 저장 단위가 단순하지 않습니다. 복합 커맨드(;나 |로 연결된 커맨드)를 승인할 경우, 승인이 필요한 서브 커맨드마다 별도의 규칙이 저장되며, 하나의 복합 커맨드당 최대 5개까지 저장됩니다. 한 번의 승인으로 allow 배열이 몇 줄씩 늘어날 수도 있는 것입니다.
// A님이 승인한 후
"allow": ["PowerShell(New-Item *)", "PowerShell(git commit *)"]
// B님이 다른 커맨드를 승인한 후
...
여러 사람이 동일한 배열의 인접한 위치를 편집하게 되므로, 머지(Merge) 시 충돌이 발생하기 쉬운 형태가 됩니다. 일상적으로 발생하는 차이점이기 때문에 은근히 스트레스가 쌓입니다.
모든 승인이 여기에 저장되는 것은 아닙니다.
파일 변경(Edit / Write)의 "앞으로 확인하지 않음"은 파일에 저장되지 않으며, 세션 종료 시까지만 유효합니다. 영구 저장되는 것은 Bash와 PowerShell의 커맨드 승인입니다.
게다가, 자동 생성된 규칙에는 다음과 같은 환경 고유의 문자열이 아무렇지 않게 섞여 들어갑니다.
"Bash(python /c/Users/007476/AppData/Local/Temp/claude/.../scratchpad/dump.py)"
사용자 이름이나 임시 폴더의 UUID가 그대로 들어 있어, 다른 사람의 환경에서는 일치하지 않습니다. 공유할 가치가 없을 뿐만 아니라, 노이즈가 될 뿐입니다.
더불어, local이라는 이름은 "각자의 로컬 환경 고유의 것"을 가리키는 일반적인 관습입니다. 이것이 커밋되어 있으면, 다른 멤버 입장에서는 "이것이 팀의 소유물인지, 누군가 실수로 올린 것인지" 판단할 수 없습니다.
리포지토리 루트에서 다음을 실행합니다.
echo ".claude/settings.local.json" >> .gitignore
git rm --cached .claude/settings.local.json # 이미 커밋된 경우에만
git add .gitignore && git commit -m "chore: untrack local claude settings"
git rm --cached는 파일을 로컬에는 남겨둔 채 Git의 관리 대상에서 제외하는 커맨드입니다.
아직 한 번도 커밋하지 않았다면 필요하지 않습니다.
이렇게 하면, 신뢰 다이얼로그를 승낙한 폴더라면 당신의 allow 규칙이 리포지토리 공급(repository-supplied) 취급을 받지 않고 그대로 적용됩니다. clone한 다른 멤버의 환경에는 이 파일이 만들어지지 않으며, 각자가 자신의 승인을 쌓아가는 형태로 돌아갑니다.
글로벌 git excludes에 의존하지 않고 프로젝트의 .gitignore에도 작성해 두면, 팀원 전원의 환경에서 확실하게 제외됩니다.
팀원 모두에게 배포하고 싶은 규칙은 .claude/settings.json에 직접 작성하여 커밋합니다.
settings.local.json의 내용을 그대로 복사하는 것은 피하십시오.
자동 생성된 규칙에는 공유에 적합하지 않은 것들이 대량으로 섞여 있습니다. 제 환경에서는 51건 중 공유에 견딜 수 있는 것은 13건뿐이었습니다.
제외해야 할 것은 대체로 다음 4가지 분류입니다.
- UUID가 포함된 임시 폴더 경로… 세션마다 변경되므로 다시는 일치하지 않습니다.
- 사용자 고유의 절대 경로 (Absolute Path)… 다른 팀원의 환경에는 존재하지 않습니다.
- 일회성 구체적 파일명… 재사용되지 않습니다.
- 임의 코드 실행 (Arbitrary Code Execution)이 될 수 있는 것…
Bash(python -c ' *)나Bash(node *)등.
allow로 공유할 경우, 다른 팀원의 환경에서 임의의 스크립트가 확인 없이 실행될 수 있습니다.
남겨두어야 할 것은 다음과 같은 범용적인 규칙입니다.
{
"permissions": {
"allow": [
...
]
}
}
앞서 언급했듯이, deny 규칙은 신뢰 대화 상자(trust dialog)의 승인을 기다리지 않고 즉시 적용됩니다. clone 직후부터 보호가 작동하므로, 공유 파일에 작성할 가치가 높은 부분입니다.
{
"permissions": {
"deny": [
...
]
}
}
Read와 Edit를 모두 작성하는 데에는 이유가 있습니다.
Read에 대한 deny 규칙은 동일한 경로에 대한 Edit 도구도 차단하지만 (v2.1.208 이후), Write와 NotebookEdit는 대상에서 제외됩니다. 어떤 도구로도 변경을 허용하고 싶지 않은 경로에는 Edit의 deny 규칙을 별도로 추가해야 합니다.
다소 복잡하지만, 파일 권한 체크 시 참조되는 것은 Edit(path)와 Read(path) 규칙뿐입니다. Write(path)나 NotebookEdit(path)라고 작성해도 수용은 되지만 참조되지는 않습니다. Edit 규칙이 모든 파일 편집 도구를 커버하므로, Edit으로 작성하는 것이 정답입니다.
또한 PowerShell에서는 별칭(Alias)이 대조 전에 정규화됩니다. PowerShell(Remove-Item *)라고 작성하면 del이나 rm에도 일치하므로, Bash 측보다 확실하게 작동합니다.
deny 규칙은 allow 규칙보다 먼저 평가되며, 넓은 범위의 deny는 좁은 범위의 allow를 포함하여 모두 차단합니다. deny에 예외를 두는 것은 불가능합니다.
Bash(git push *)와 같은 규칙을 넣는 경우에는, 해당 작업을 Claude에게 요청할 수 없게 된다는 점을 인지한 상태에서 추가해야 합니다.
.claude/settings.json을 배치했다면, Claude Code를 종료하고 프로젝트 루트에서 다시 실행합니다. 실행 시 표시되는 신뢰 대화 상자에서 "Yes, I trust this folder"를 선택하면, 그 즉시 allow 규칙과 additionalDirectories가 적용됩니다.
반영 여부는 /permissions로 확인할 수 있습니다.
/permissions
모든 권한 규칙과 각 규칙이 어떤 settings 파일에서 유래했는지 목록이 표시되므로, 목적한 규칙의 출처가 .claude/settings.json으로 되어 있다면 완료된 것입니다.
.claude/settings.local.json을 추적 대상에서 제외해야 하는 이유를 정리합니다.
- 추적 대상에 포함되면 "리포지토리 유래일 수도 있다"라고 판정되어, 사용자 고유의
allow규칙과additionalDirectories가 신뢰 대화 상자의 심사 대상이 됩니다. - 승인할 때마다 자동으로 추가되므로 충돌(Conflict)이 빈번하게 발생하며, 환경 고유의 경로가 섞여 공유할 의미가 없어집니다.
보통은 Claude Code가 글로벌 git excludes에 자동으로 추가해주기 때문에, 이 문제에 직면하는 경우는 파일을 직접 만들었거나, Write 도구로 작성하게 했거나, 혹은 추적 대상에 포함된 리포지토리를 인계받은 경우로 한정됩니다.
"local이 붙은 파일은 커밋하지 않는다"라는 관습을 따르면 해결될 문제이기도 하지만, 그 이면에 '워크스페이스 신뢰(workspace trust)'라는 메커니즘이 있다는 것을 알고 있으면, 예상치 못한 동작을 만났을 때 원인을 파악하기 훨씬 쉬워집니다.
공유해야 할 것은 settings.json에, 개인적인 것은 settings.local.json에. 이 구분을 처음에 명확히 해두는 것을 추천합니다.
- 권한 설정 (Configure permissions) - Claude Code Docs
- Claude Code 설정 (Claude Code settings) - Claude Code Docs
- gitignore - Git Documentation
프로그래밍 코칭 JISOU에서는 새로운 멤버를 모집하고 있습니다.
일본 최고의 아웃풋 (Output) 커뮤니티에서 커리어 업을 해보지 않으시겠습니까?
관심이 있으신 분은 꼭 홈페이지를 방문해 주세요!
▼▼▼
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기