diff --git a/.claude/settings.json b/.claude/settings.json index 02aa846..17c104d 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -1,11 +1,10 @@ { - "_description": "너드나비스 조직 공용 Claude Code permission 설정. PD님의 일괄 승인 원칙(memory/org/feedback_md_approval.md·feedback_approval_process.md)을 harness 차원에서 구현. 모든 PC에서 동일하게 적용되도록 git 커밋 대상. 개별 PC 예외·실험적 명령은 .claude/settings.local.json(gitignore)에 기록.", + "_description": "너드나비스 조직 공용 Claude Code permission 설정 (SOT). PD님의 일괄 승인 원칙(memory/org/feedback_md_approval.md·feedback_approval_process.md)을 harness 차원에서 구현. 모든 PC에서 동일하게 적용되도록 git 커밋 대상. 개발실/·기획실/에도 동일 사본이 배치되어야 자식 디렉토리에서 세션을 시작해도 동일 권한이 적용됨 (Claude Code는 .claude/ 계층 auto-merge 미지원). 동기화는 setup_windows.ps1이 수행.", "permissions": { "allow": [ "Read", "Glob", "Grep", - "LS", "TodoWrite", "Edit", "Write", @@ -40,8 +39,9 @@ "Bash(false)", "Bash(powershell.exe:*)", "Bash(powershell:*)", - "Bash(fsutil reparsepoint:*)", - "Bash(npm run:*)", + "Bash(fsutil:*)", + "Bash(cmd:*)", + "Bash(npm:*)", "Bash(npx:*)", "Bash(node:*)", "Bash(python:*)", @@ -52,21 +52,24 @@ "WebSearch" ], "deny": [ - "Bash(rm -rf /*)", - "Bash(rm -rf ~*)", - "Bash(rm -rf $HOME*)", + "Bash(rm:*)", + "Bash(rmdir:*)", "Bash(sudo:*)", - "Bash(chmod 777:*)", - "Bash(format:*)", "Bash(dd:*)", "Bash(mkfs:*)", - "Bash(:(){ :|:& };:)", + "Bash(format:*)", + "Bash(chmod 777:*)", + "Bash(chown:*)", + "Bash(shutdown:*)", + "Bash(reboot:*)", "Write(/etc/**)", "Write(/System/**)", "Write(C:/Windows/**)", + "Write(C:\\Windows\\**)", "Edit(/etc/**)", "Edit(/System/**)", - "Edit(C:/Windows/**)" + "Edit(C:/Windows/**)", + "Edit(C:\\Windows\\**)" ] } } diff --git a/memory/org/feedback_permissions_portability.md b/memory/org/feedback_permissions_portability.md index abc7543..9bec899 100644 --- a/memory/org/feedback_permissions_portability.md +++ b/memory/org/feedback_permissions_portability.md @@ -19,6 +19,18 @@ Claude Code의 승인 체계는 **2계층**으로 분리되어 있다: **결론**: 조직 공용 permission은 반드시 `.claude/settings.json`(프로젝트 루트)에 선언·커밋해야 PC 독립성이 보장된다. +## 자식 디렉토리 전파 원칙 (너드나비스 구조 특수사항) + +Claude Code는 `.claude/` 폴더 1개만 프로젝트 루트로 인식하며 **부모 방향 auto-merge를 지원하지 않는다**. 너드나비스 조직 레포는 루트 외에 `개발실/.claude/`·`기획실/.claude/`가 이미 존재(agents·commands·skill-modules 용). 이 때문에 자식 디렉토리에서 세션을 시작하면 루트의 settings.json이 무시된다. + +**해결 구조**: +- **SOT**: `.claude/settings.json` (루트). 모든 변경은 이 파일을 먼저 편집. +- **파생**: `개발실/.claude/settings.json`·`기획실/.claude/settings.json` — 루트 SOT의 복사본. +- **동기화**: `setup/setup_windows.ps1`이 루트 SOT → 두 부서로 자동 복제. 셋업 스크립트 실행 시마다 갱신. +- **수동 동기화 (스크립트 미실행 환경)**: 루트 settings.json 수정 후 두 부서 파일에도 동일 내용 반영 후 일괄 커밋. + +**검증법**: 각 부서 디렉토리에서 `.claude/settings.json` 존재 여부 확인. 파일이 같은 내용인지 diff로 점검. + ## 권장 구성 ```json diff --git a/setup/setup_windows.ps1 b/setup/setup_windows.ps1 index eb8fd5d..0ece6c8 100644 --- a/setup/setup_windows.ps1 +++ b/setup/setup_windows.ps1 @@ -98,4 +98,24 @@ if ($hashDirs.Count -eq 0) { Write-Warning "Claude 프로젝트 해시 폴더를 찾지 못했습니다. 수동 연결 필요." } +# 4. .claude/settings.json 부서 동기화 (루트 SOT → 개발실/기획실 복제) +# Claude Code는 .claude/ 계층 auto-merge를 지원하지 않으므로 자식 디렉토리에서 세션 시작 시 +# 루트 settings.json을 인식하지 못함. 이를 우회하기 위해 루트 settings.json을 부서 디렉토리로 복제. +$rootSettings = Join-Path $NerdNavisRoot ".claude\settings.json" +if (Test-Path $rootSettings) { + $deptPaths = @("개발실", "기획실") + foreach ($dept in $deptPaths) { + $deptClaudeDir = Join-Path $NerdNavisRoot "$dept\.claude" + $deptSettings = Join-Path $deptClaudeDir "settings.json" + if (-not (Test-Path $deptClaudeDir)) { + New-Item -ItemType Directory -Path $deptClaudeDir -Force | Out-Null + } + Copy-Item -Path $rootSettings -Destination $deptSettings -Force + Write-Host "settings.json 동기화: $dept/.claude/settings.json" + } +} else { + Write-Warning "루트 .claude/settings.json 미발견. 부서 동기화 생략." +} + Write-Host "셋업 완료. 'git pull'로 최신 상태 유지 권장." +Write-Host "※ .claude/settings.json 변경사항은 세션 재시작 후 적용됨." diff --git a/개발실/.claude/settings.json b/개발실/.claude/settings.json new file mode 100644 index 0000000..17c104d --- /dev/null +++ b/개발실/.claude/settings.json @@ -0,0 +1,75 @@ +{ + "_description": "너드나비스 조직 공용 Claude Code permission 설정 (SOT). PD님의 일괄 승인 원칙(memory/org/feedback_md_approval.md·feedback_approval_process.md)을 harness 차원에서 구현. 모든 PC에서 동일하게 적용되도록 git 커밋 대상. 개발실/·기획실/에도 동일 사본이 배치되어야 자식 디렉토리에서 세션을 시작해도 동일 권한이 적용됨 (Claude Code는 .claude/ 계층 auto-merge 미지원). 동기화는 setup_windows.ps1이 수행.", + "permissions": { + "allow": [ + "Read", + "Glob", + "Grep", + "TodoWrite", + "Edit", + "Write", + "MultiEdit", + "NotebookEdit", + "Bash(git:*)", + "Bash(gh:*)", + "Bash(ls:*)", + "Bash(cat:*)", + "Bash(head:*)", + "Bash(tail:*)", + "Bash(grep:*)", + "Bash(rg:*)", + "Bash(find:*)", + "Bash(echo:*)", + "Bash(pwd)", + "Bash(cd:*)", + "Bash(mkdir:*)", + "Bash(touch:*)", + "Bash(cp:*)", + "Bash(mv:*)", + "Bash(diff:*)", + "Bash(wc:*)", + "Bash(sort:*)", + "Bash(uniq:*)", + "Bash(tr:*)", + "Bash(sed:*)", + "Bash(awk:*)", + "Bash(xxd:*)", + "Bash(printf:*)", + "Bash(true)", + "Bash(false)", + "Bash(powershell.exe:*)", + "Bash(powershell:*)", + "Bash(fsutil:*)", + "Bash(cmd:*)", + "Bash(npm:*)", + "Bash(npx:*)", + "Bash(node:*)", + "Bash(python:*)", + "Bash(python3:*)", + "Bash(pytest:*)", + "Bash(dotnet:*)", + "WebFetch", + "WebSearch" + ], + "deny": [ + "Bash(rm:*)", + "Bash(rmdir:*)", + "Bash(sudo:*)", + "Bash(dd:*)", + "Bash(mkfs:*)", + "Bash(format:*)", + "Bash(chmod 777:*)", + "Bash(chown:*)", + "Bash(shutdown:*)", + "Bash(reboot:*)", + "Write(/etc/**)", + "Write(/System/**)", + "Write(C:/Windows/**)", + "Write(C:\\Windows\\**)", + "Edit(/etc/**)", + "Edit(/System/**)", + "Edit(C:/Windows/**)", + "Edit(C:\\Windows\\**)" + ] + } +} diff --git a/기획실/.claude/settings.json b/기획실/.claude/settings.json new file mode 100644 index 0000000..17c104d --- /dev/null +++ b/기획실/.claude/settings.json @@ -0,0 +1,75 @@ +{ + "_description": "너드나비스 조직 공용 Claude Code permission 설정 (SOT). PD님의 일괄 승인 원칙(memory/org/feedback_md_approval.md·feedback_approval_process.md)을 harness 차원에서 구현. 모든 PC에서 동일하게 적용되도록 git 커밋 대상. 개발실/·기획실/에도 동일 사본이 배치되어야 자식 디렉토리에서 세션을 시작해도 동일 권한이 적용됨 (Claude Code는 .claude/ 계층 auto-merge 미지원). 동기화는 setup_windows.ps1이 수행.", + "permissions": { + "allow": [ + "Read", + "Glob", + "Grep", + "TodoWrite", + "Edit", + "Write", + "MultiEdit", + "NotebookEdit", + "Bash(git:*)", + "Bash(gh:*)", + "Bash(ls:*)", + "Bash(cat:*)", + "Bash(head:*)", + "Bash(tail:*)", + "Bash(grep:*)", + "Bash(rg:*)", + "Bash(find:*)", + "Bash(echo:*)", + "Bash(pwd)", + "Bash(cd:*)", + "Bash(mkdir:*)", + "Bash(touch:*)", + "Bash(cp:*)", + "Bash(mv:*)", + "Bash(diff:*)", + "Bash(wc:*)", + "Bash(sort:*)", + "Bash(uniq:*)", + "Bash(tr:*)", + "Bash(sed:*)", + "Bash(awk:*)", + "Bash(xxd:*)", + "Bash(printf:*)", + "Bash(true)", + "Bash(false)", + "Bash(powershell.exe:*)", + "Bash(powershell:*)", + "Bash(fsutil:*)", + "Bash(cmd:*)", + "Bash(npm:*)", + "Bash(npx:*)", + "Bash(node:*)", + "Bash(python:*)", + "Bash(python3:*)", + "Bash(pytest:*)", + "Bash(dotnet:*)", + "WebFetch", + "WebSearch" + ], + "deny": [ + "Bash(rm:*)", + "Bash(rmdir:*)", + "Bash(sudo:*)", + "Bash(dd:*)", + "Bash(mkfs:*)", + "Bash(format:*)", + "Bash(chmod 777:*)", + "Bash(chown:*)", + "Bash(shutdown:*)", + "Bash(reboot:*)", + "Write(/etc/**)", + "Write(/System/**)", + "Write(C:/Windows/**)", + "Write(C:\\Windows\\**)", + "Edit(/etc/**)", + "Edit(/System/**)", + "Edit(C:/Windows/**)", + "Edit(C:\\Windows\\**)" + ] + } +}