Claude Code Windows 경로 문제: 공백·한글·CRLF가 깨뜨리는 곳
권한 규칙의 deny에 Read(/c/work/app/secret.txt)를 적어 두고 Claude Code에 그 파일을 읽게 했습니다. 그대로 읽히더라고요. 오류도 경고도 없이요.
같은 파일을 Read(//c/work/app/secret.txt)로 적으면 막혔습니다. 슬래시 하나 차이였죠.
Windows에서는 같은 폴더도 자리마다 적는 법이 다릅니다. settings.json 값은 C:\\Program Files\\...처럼 역슬래시를 두 번, 권한 규칙은 //c/Users/...처럼 슬래시 두 개로 시작하고, 훅에서는 받은 경로의 \를 /로 바꾼 뒤 비교해요. 잘못 적어도 대부분 오류 없이 조용히 무시되니까, 넣은 뒤에는 실제로 막히는지 꼭 한 번 시험해 보세요.
2026년 9월 16일 공식 문서와 공개 이슈 5건으로 처음 썼고, 10월 5일 Windows 11 · PowerShell 5.1 테스트 환경에서 Claude Code 2.1.286과 Git for Windows 2.53.0(bash 5.2.37)으로 다섯 가지를 직접 확인해 더했습니다.
설치가 아직이라면 PowerShell에서 Claude Code를 설치하고 첫 작업을 시키는 순서부터 보세요.
확인한 버전·환경
- Claude Code 2.1.286 · Windows 11 · Windows PowerShell 5.1 · 확인일 2026-10-05
- Git for Windows 2.53.0 (bash 5.2.37) · Windows 11 · 확인일 2026-10-05
자리마다 다른 경로 표기
Claude Code에서 경로를 다루는 자리는 넷입니다. 표기가 자리마다 다르고, 서로 자동으로 바뀌지 않아요.
문제는 한 표기를 다른 자리에 옮겼을 때 오류가 아니라 침묵으로 끝난다는 겁니다.
settings.json에 역슬래시를 하나만 쓰면: JSON에서\는 이스케이프 문자라 경로가 깨집니다.\\로 두 번 적어야 한 개가 됩니다.- 권한 규칙에
/c/...를 쓰면: 절대 경로가 아니라 설정 파일 기준 상대 경로가 되어 아무것도 걸리지 않습니다. - 훅에서 슬래시로 비교하면: 훅이 받는 경로는 역슬래시라 절대 맞지 않고, 막으려던 도구 호출이 그대로 진행됩니다.
- Git Bash에 보이는
/c/Users/...를 옮겨 적으면: 위 두 경우 중 하나가 됩니다.
WSL로 옮기면 표기 걱정은 줄지만 대가가 있습니다. WSL에서 Windows 쪽 파일(/mnt/c/)을 다루면 디스크 읽기가 느려 검색 결과가 평소보다 적게 돌아올 수 있고, 이때도 claude doctor는 검색을 정상으로 표시해요. WSL을 쓴다면 프로젝트를 Linux 파일시스템(/home/ 아래)에 두세요.
Git Bash 경로를 직접 지정할 때
Git을 기본 위치에 설치했다면 지정할 필요가 없습니다. Git for Windows가 아예 없으면 Claude Code는 PowerShell을 셸 도구로 씁니다. CLAUDE_CODE_GIT_BASH_PATH가 없을 때 찾는 순서는 이렇습니다.
- 기본 설치 위치
C:\Program Files\Git,C:\Program Files (x86)\Git PATH에 있는git의 설치 폴더 안bin\bash.exe
2단계에서는 Claude Code를 실행한 폴더 안이나 그 아래 node_modules·.venv·env에 있는 git은 건너뜁니다. 프로젝트가 가져다 둔 실행 파일을 돌리지 않으려는 장치예요.
Git이 그런 자리나 다른 곳에 있다면 직접 지정합니다. 위치는 PowerShell의 where.exe git으로 찾습니다.
{
"env": {
"CLAUDE_CODE_GIT_BASH_PATH": "C:\\Program Files\\Git\\bin\\bash.exe"
}
}
여기서 받아들이는 파일 이름은 bash.exe·sh.exe·bash·sh뿐입니다. git-bash.exe(Git for Windows의 실행기)를 가리키거나 없는 경로를 넣었을 때는 버전에 따라 결과가 다릅니다.
| 버전 | 이름이 틀렸을 때 | 경로가 없을 때 |
|---|---|---|
| v2.1.219 이전 | 그 파일을 셸로 씀 | 시작하자마자 종료 |
| v2.1.219 이후 | 무시하고 자동 탐색 | 무시하고 자동 탐색 |
옛 버전에서 종료될 때 나오는 문구가 Claude Code was unable to find CLAUDE_CODE_GIT_BASH_PATH path입니다.
Claude Code 2.1.286에 없는 경로와 git-bash.exe를 차례로 넣어 보니, 둘 다 멀쩡히 시작했고 화면엔 아무 경고가 없었습니다. claude --debug의 디버그 로그에만 아래 줄이 남았고, 바로 다음에 자동으로 찾은 C:\Program Files\Git\bin\bash.exe를 썼어요.
[WARN] CLAUDE_CODE_GIT_BASH_PATH "C:\nope\bash.exe" not found; falling back to auto-detection
[WARN] CLAUDE_CODE_GIT_BASH_PATH "C:\Program Files\Git\git-bash.exe" is not a bash/sh binary; falling back to auto-detection
기본 위치에 Git이 있으면 잘못 넣어도 결과가 같아서, 변수가 무시되고 있다는 것조차 알기 어렵습니다. 이름도 경로도 맞는데 지정한 셸이 안 쓰인다면 AppLocker·그룹 정책·EDR 같은 보안 소프트웨어가 막고 있을 수 있습니다.
사용자 폴더 이름 자체에 공백이 있는 경우도 보고돼 있습니다. mcat1965는 2026년 4월 14일 이슈에서 프로필 경로에 공백이 있으면 Claude Code가 시작하지 못하거나 이상하게 동작하고, 유일하게 통한 방법이 CLAUDE_HOME을 공백 없는 경로로 두는 것이었다고 보고했습니다.
다만 공식 환경 변수 목록에 CLAUDE_HOME은 없고, 설정 폴더를 옮기는 변수는 CLAUDE_CONFIG_DIR입니다. 이 이슈는 not planned로 닫혔습니다.
권한 규칙의 절대 경로는 //c/로 시작
Windows 경로는 권한 규칙과 비교되기 전에 C:\Users\ → /c/Users/처럼 바뀝니다. 그래서 C 드라이브 어디든 .env를 막으려면 //c/**/.env, 모든 드라이브라면 //**/.env를 씁니다. Read·Edit 규칙은 첫 글자가 기준점을 정해요.
| 패턴 | 기준점 |
|---|---|
//path |
파일시스템 루트 |
~/path |
홈 폴더 |
/path |
그 규칙을 적은 설정 파일 |
path, ./path |
현재 폴더 |
헷갈리는 건 /path입니다. 규칙을 어느 파일에 적었느냐에 따라 풀리거든요.
프로젝트·로컬 설정이나 CLI 플래그에 적으면 작업 폴더 아래, 사용자 설정(~/.claude/settings.json)에 적으면 ~/.claude/ 아래입니다. 사용자 설정의 Read(/secrets/**)가 프로젝트의 secrets가 아니라 ~/.claude/secrets/**를 막는 이유예요.
맨 앞에 적은 시험을 표로 옮기면 이렇습니다. 같은 파일(C:\work\app\secret.txt)을 막는 deny 규칙을 세 가지로 적고 Claude Code 2.1.286에 그 파일을 읽게 했습니다.
deny에 적은 규칙(JSON 그대로) |
결과 |
|---|---|
"Read(//c/work/app/secret.txt)" |
막힘 |
"Read(/c/work/app/secret.txt)" |
그대로 읽힘(오류·경고 없음) |
"Read(C:\\work\\app\\secret.txt)" |
막힘 |
막혔을 때는 File is in a directory that is denied by your permission settings.가 나왔습니다. 역슬래시 Windows 경로도 이 버전에선 막혔지만, 공식 표기는 //c/...이니 저는 그쪽을 권합니다.
deny 규칙을 넣었는데 그 파일이 그대로 읽힌다면, 경로 표기 말고도
Read·Edit규칙은 파일 이름을 대지 않는 명령(그 폴더에서 돌린grep -r등)이나 스스로 파일을 여는 Python·Node 스크립트에는 적용되지 않는다는 점을 기억하세요.
모든 프로세스를 막아야 한다면 샌드박스가 필요한데, 샌드박스는 네이티브 Windows와 WSL 1에서는 안 되고 WSL 2에서만 됩니다. 규칙의 평가 순서는 권한 규칙이 deny·ask·allow 순으로 평가되는 방식에 있습니다.
네트워크 경로는 따로 다룹니다. \\server\share 같은 UNC 경로를 비롯해 네트워크 경로 대부분은 작업 폴더로 추가할 수 없어요. 경로를 확인하는 것만으로 그 호스트에 접속하기 때문입니다.
공유 폴더를 드라이브 문자에 연결한 뒤 그 드라이브를 --add-dir로 넘기세요.
명령 인자에 UNC 경로가 있으면 Windows 자격 증명이 그 호스트로 갈 수 있어 승인 창이 뜨고, PowerShell 도구 명령에도 같은 검사가 걸립니다.
훅에서는 역슬래시를 슬래시로 바꿔 비교
Read에 거는 PreToolUse 훅이 받은 입력을 열어 봤습니다. 같은 훅에서 $PWD는 /c/work/app이었는데, 경로는 이렇게 왔어요(관계없는 필드는 줄였습니다).
"cwd":"C:\\work\\app", … "tool_input":{"file_path":"C:\\work\\app\\notes.txt"}
훅이 받는 tool_input.file_path는 Windows에서 역슬래시 절대 경로입니다. 훅이 Git Bash에서 돌아도, PostToolUse여도 같습니다. 그래서 secret.txt를 막는 훅을 두 가지로 만들어 보니 결과가 갈렸습니다.
| 훅 | 결과 |
|---|---|
입력에서 /app/secret을 바로 찾음 |
막지 못함(종료 코드 0, 파일 내용이 나옴) |
\\를 /로 바꾼 뒤 찾음 |
막힘 |
막혔을 때 Claude 쪽에는 PreToolUse:Read hook error: [bash guard-norm.sh]: blocked: secret file이 전달됐습니다. 테스트 환경의 Git Bash에는 jq가 없어서, JSON 원문의 \\를 그대로 바꾸는 방식으로 썼습니다.
#!/bin/bash
INPUT=$(cat)
# JSON 안에서 역슬래시는 \\ 두 글자로 온다. 슬래시로 바꾼 뒤 비교한다.
NORM=$(printf '%s' "$INPUT" | sed 's#\\\\#/#g')
if printf '%s' "$NORM" | grep -q '/app/secret'; then
echo "blocked: secret file" >&2
exit 2
fi
exit 0
jq가 있다면 값을 꺼낸 뒤 Bash는 FILE_PATH="${FILE_PATH//\\//}", Python은 file_path.replace("\\", "/")로 바꿉니다. 절대 경로라서 ^로 앞을 고정하지 말고 /src/ 같은 조각으로 맞추세요. 훅의 이벤트 종류는 훅으로 매번 실행되는 검사를 거는 방법에 있습니다.
CRLF 스크립트는 Git Bash에선 돌았지만
trade-art는 2026년 2월 14일 이슈에서 플러그인이 받은 훅 스크립트가 CRLF로 저장돼 이런 오류가 났다고 보고했습니다.
cleanup-check.sh: line 2: $'\r': command not found
cleanup-check.sh: line 5: $'\r': command not found
cleanup-check.sh: line 32: syntax error: unexpected end of file
같은 이슈는 훅 설정의 C:\Users\YourName\... 경로가 /bin/bash로 넘어가며 역슬래시가 사라져 No such file or directory가 났다고도 적었습니다. 보고자는 경로를 /mnt/c/Users/...로 바꾸고 tr -d '\r'로 LF로 변환해 넘겼고, 플러그인을 올릴 때마다 다시 해야 했다고 합니다. not planned로 닫혔습니다.
그런데 CRLF로 저장한 스크립트를 PreToolUse 훅에 걸어 보니, Git for Windows bash 5.2.37에서는 오류가 없었습니다. 변수 대입·출력·종료 코드를 보는 세 줄짜리 CRLF 스크립트도 값과 종료 코드가 정확했고, bash.exe·sh.exe 모두 같았어요. 그러니 $'\r': command not found가 보인다면 어느 bash(WSL 등)로 실행되는지부터 확인해 보세요.
그래도 같은 .sh를 WSL이나 Linux·macOS에서도 돌린다면 저장소에서는 LF로 둡니다. tr -d '\r' < script.sh > script.tmp && mv script.tmp script.sh로 바꾸고, .gitattributes에 *.sh text eol=lf를 넣으면 다시 들어오지 않습니다. 파일이 바뀔 때마다 걷어 내려면 공식 훅 문서의 FileChanged 예시를 씁니다.
#!/bin/bash
FILE=$(jq -r .file_path)
if grep -q $'\r$' "$FILE"; then
perl -pi -e 's/\r$//' "$FILE"
fi
여기서 grep 조건은 perl이 지우는 것(줄 끝 CR)과 정확히 같아야 합니다. 느슨하면 perl -i가 바꿀 게 없어도 파일을 다시 쓰고, 그때마다 훅이 또 돌아 끝없이 반복해요.
Bash 도구가 \\에서 역슬래시 하나를 지운다
unixtrail은 2026년 8월 25일 이슈에서 Windows·Git Bash에서 Bash 도구가 명령 문자열 속 \\ 쌍마다 역슬래시 하나를 없앤다고 보고했습니다. 작은따옴표·heredoc·따옴표 없음 모두 같았고 \"·\t·\d·\s와 단독 역슬래시는 그대로였다고 합니다. 원인은 추정만 있고 이슈는 열려 있습니다.
Claude Code 2.1.286에 Bash 도구로 printf '%s' 'a\\b' | od -c를 실행하게 했더니 0000000 a \ b가 나왔습니다. 작은따옴표 속 \\는 두 글자로 남아야 하는데 하나가 사라진 거죠. 역슬래시가 든 정규식이나 경로를 넘길 때는 결과를 확인하거나, 내용을 파일로 저장해 쓰게 하세요.
한글 폴더 이름이 겹치는 문제
한글 이름 폴더 셋에서 Claude Code 2.1.286을 한 번씩 실행하고, ~/.claude/projects/ 아래에서 기록이 쌓인 폴더를 찾아봤습니다.
| 작업 폴더 | 기록이 쌓인 폴더 |
|---|---|
C:\work\경로-하나 |
C--work------ |
C:\work\경로-둘 |
C--work----- |
C:\work\경로-셋 |
C--work----- |
한글 한 글자와 하이픈이 각각 - 하나가 됐고, 글자 수가 같은 경로-둘과 경로-셋은 같은 폴더에 대화 기록을 함께 쌓았습니다. cis1273-ai가 2026년 9월 11일 이슈에서 보고한 충돌(한쪽 폴더에서 쓴 메모리 파일이 다른 폴더 세션에 실림)이 그대로 재현된 거예요. 이슈는 열려 있고 우회법은 없습니다.
정리할 때도 문제가 됩니다. 경로-둘의 기록을 지우는 명령(2.1.286의 claude project purge 'C:\work\경로-둘' --dry-run, 2.1.288부터 claude purge)의 삭제 계획에 공유 폴더 전체가 잡혀, 경로-셋의 기록까지 함께 지워지는 구조였습니다.
가장 간단한 회피책은 폴더 이름에 영문을 섞는 겁니다. 저장 폴더 이름을 직접 정하는 CLAUDE_CODE_PROJECT_DIR_NAME(v2.1.234 이상)도 있지만, Claude Code를 품고 세션마다 설정 폴더를 따로 주는 프로그램용이라 조건이 까다로워요.
CLAUDE_CONFIG_DIR과 함께 써야 하고, 기본~/.claude아래에서 쓰면 모든 프로젝트가 한 폴더로 합쳐집니다.- 값은 영문자·숫자·하이픈·밑줄 1~64자이고,
con같은 Windows 장치 이름은 피합니다. - 셸 환경 변수로만 읽으므로 설정 파일의
env로는 지정할 수 없습니다.
한글 폴더에서 실행 중 인코딩 오류가 나는 경우도 있습니다. Gayasaka-Rin은 2026년 3월 20일 이슈에서 아래 오류가 상태 표시줄을 덮는다고 보고했고, 사용자용 우회법 없이 not planned로 닫혔습니다.
Error: 'utf-8' codec can't encode character '\udcec' in position 31: surrogates not allowed
PowerShell 쪽 한글 처리는 Claude Code 버전에 따라 다릅니다. v2.1.214 이상에서는 PowerShell 5.1의 >·>>가 UTF-8 파일을 쓰고 네이티브 명령에 넘기는 텍스트도 UTF-8로 보냅니다.
그 이전에는 >가 UTF-16LE 파일을 썼고, 한글 입력이 ?로 도착했고, 한글을 출력하는 Python 스크립트가 UnicodeEncodeError로 죽을 수 있었습니다.
사용자가 연 PowerShell 창 자체의 인코딩 때문에 깨지는 경우는 Windows PowerShell 5.1에서 Claude Code·Codex의 한글이 깨지는 세 경우와 해결에 있습니다.
마치며
이번에 확인한 것들의 공통점은 틀려도 아무 말이 없다는 점이었습니다. /c/로 시작한 규칙은 아무것도 막지 못했고, 잘못 넣은 Git Bash 경로는 디버그 로그에만 흔적을 남겼고, 한글 폴더 둘은 소리 없이 기록을 한 곳에 쌓았어요. Windows에서 경로를 적는 설정은 넣은 것으로 끝이 아니라, 한 번 걸려 봐야 걸린 겁니다.
그래서 deny 규칙을 설정해 뒀다면 지금 그 파일을 Claude에게 실제로 읽게 해서 막히는지 확인해 보세요. 한글 폴더를 여러 개 쓴다면 이름에 영문을 섞어 두시고요. 증상이 경로 문제인지 다른 층의 문제인지부터 가르고 싶다면 증상으로 어느 층에서 막혔는지 가르는 순서를 이어서 보면 됩니다.
참고한 공식 자료
모두 2026년 9월 16일에 확인했습니다.
- Permissions — Claude Code Docs: 경로 패턴 4종의 기준점,
//c/**/.env, UNC 경로 제한 - Hooks — Claude Code Docs: Windows에서 훅이 받는 경로 형식과 구분자 정규화,
FileChanged로 CRLF 걷어 내기 - Troubleshoot installation and login — Claude Code Docs: Git Bash 탐색 순서,
CLAUDE_CODE_GIT_BASH_PATH가 받는 이름, v2.1.219 전후 차이 - Advanced setup — Claude Code Docs: Git for Windows의 역할, 샌드박스 지원 여부
- Tools reference — Claude Code Docs: v2.1.214 이상 PowerShell 인코딩 동작과 그 이전 동작
- Sessions — Claude Code Docs:
CLAUDE_CODE_PROJECT_DIR_NAME의 조건과 필요 버전 - Environment variables — Claude Code Docs:
CLAUDE_CONFIG_DIR,CLAUDE_CODE_GIT_BASH_PATH - Troubleshooting — Claude Code Docs: WSL에서 검색 결과가 줄어드는 문제
인용한 공개 사례
이 중 #93743(기록 폴더 충돌)과 #89392(역슬래시 소실)는 Claude Code 2.1.286에서 같은 증상을 확인했고, #25711의 CRLF 오류는 Git for Windows bash에서 나지 않았습니다.
- mcat1965, 2026-04-14, Claude Code CLI fails on Windows when username path contains spaces (#47943) — 프로필 경로의 공백으로 시작 실패,
CLAUDE_HOME우회법, not planned로 종료 - trade-art, 2026-02-14, Plugin hooks fail on Windows: wrong path format and CRLF line endings in shell scripts (#25711) — 훅 경로의 역슬래시 소실과 CRLF 스크립트 오류, not planned로 종료
- cis1273-ai, 2026-09-11, Project memory/session storage collides across different projects due to non-ASCII path slug encoding (#93743) — 한글 폴더 이름이 대시로 바뀌어 메모리가 섞임, 열려 있음
- Gayasaka-Rin, 2026-03-20, UTF-8 surrogate encoding error on Windows with non-ASCII (Korean) directory paths (#36464) — 한글 폴더에서 surrogate 인코딩 오류, not planned로 종료
- unixtrail, 2026-08-25, Bug: Bash tool silently strips backslashes on Windows/Git Bash (#89392) — 명령 문자열의
\\에서 역슬래시 하나가 사라짐, 열려 있음
변경 이력
- 2026-10-05 — Windows 11에서 직접 확인한 결과 다섯 가지를 더했습니다. Git Bash 경로 변수 오설정 시 경고, 권한 규칙 표기 세 가지의 결과, 훅이 받는 경로와 정규화 훅, CRLF 스크립트가 Git Bash에서는 오류 없이 돈 것, 한글 폴더의 저장 디렉터리 충돌입니다. 역슬래시로 적은 권한 규칙이 걸리지 않는다고 적은 부분은 직접 확인 결과 막혀서 고쳤습니다.