Claude Code의 claude -p는 쓰기 거부되어도 종료 코드 0으로 끝난다 — 스크립트에서는 출력과 파일로 판단해야 한다
요약
Claude Code를 스크립트의 비대화 모드(`claude -p`)로 호출할 경우, 파일 쓰기 권한 문제로 작업이 거부되어도 종료 코드는 0으로 유지됩니다. 따라서 성공 여부를 판단하려면 단순히 종료 코드만 확인할 것이 아니라, 실제 파일 존재 유무와 JSON 출력 형식의 `permission_denials` 필드를 함께 검토해야 합니다.
핵심 포인트
- 비대화 모드에서 쓰기 실패 시에도 종료 코드는 0으로 유지됩니다.
- 성공 판단은 `$LASTEXITCODE`만으로는 부족하며, 파일 존재 여부를 확인해야 합니다.
- `--output-format json`을 사용하면 거부된 작업 기록이 `permission_denials`에 남습니다.
- 권한 문제로의 거부는 '실행 실패'가 아닌 '요청 일부 수행 불가'로 처리됩니다.
Claude Code(Anthropic의 터미널에서 작동하는 AI 코딩 에이전트)를 claude -p
(비대화 모드, non-interactive mode)로 스크립트에서 호출하면, 파일 쓰기가 권한 확인이나 설정 문제로 거부되어도 종료 코드(exit code)는 0입니다. --output-format json의 is_error 역시 false이며, subtype은 success입니다.
' $LASTEXITCODE -eq 0 이면 성공'이라고만 판단하면 아무것도 생성되지 않았는데도 다음 처리 단계로 진행됩니다. 기대하는 파일이 실제로 존재하는지와 JSON의 permission_denials를 함께 판단하는 것이 안전합니다.
확인 환경: Claude Code 2.1.318, Windows 11 Pro, PowerShell 5.1. 확인일 2026-11-06. 경로는 <TEMP>로 대체했습니다.
- 비대화 모드는 '성공 시 0, 실행 실패 시 0이 아닌 값'으로 종료됩니다(https://code.claude.com/docs/en/headless, 2026-11-06 확인).
- Manual 모드(아무것도 지정하지 않은 기본값)의
-p는 승인이 필요한 작업은 무언가 승인되지 않는 한 거부됩니다(동일 페이지). -p에서는 설정 파일 오류도 대화 상자를 표시하지 않고, 손상된 설정을 건너뛰고 계속 진행합니다(https://code.claude.com/docs/en/settings, 2026-11-06 확인).
권한 문제로 거부되는 것은 '실행 실패'가 아니라 '요청의 일부를 수행할 수 없었음'으로 처리되므로 종료 코드에는 반영되지 않는 것으로 정리됩니다.
빈 임시 폴더에서 파일을 하나 만들도록 요청했습니다. 저는 Claude Code 화면 내에서 시도했기 때문에, 상위 세션의 환경 변수(CLAUDE로 시작하는 것)를 지운 새로운 PowerShell에서 실행했습니다.
Set-Location <TEMP>\case
[Console]::OutputEncoding = [Text.UTF8Encoding]::new($false) # claude의 UTF-8 출력을 올바르게 받기
$out = claude -p '이 폴더에 hello.txt라는 파일을 만들고, 내용물은 hi 한 줄로 해주세요.' --output-format text 2>$null
...
exit=0
exists=False
hello.txt는 아직 만들어지지 않았습니다. 이 폴더에 대한 쓰기를 허가해주지 않으셨기 때문에, 파일은 생성되지 않았습니다.
...
응답 문구는 실행마다 조금씩 다르지만, 이 조건(모드 지정 없음)으로 5번 시도했을 때 모두 종료 코드 0이며 파일이 없었습니다.
--output-format json을 사용하면, 거부된 작업은 permission_denials에 기록됩니다(발췌).
{
"type": "result",
"subtype": "success",
...
.claude\settings.json에 deny 규칙을 작성하고, --permission-mode acceptEdits(파일 편집을 확인 없이 허용하는 모드)와 --output-format json으로 동일한 요청을 했습니다. 아래 출력은 JSON의 주요 항목을 Format-List로 표시한 것입니다.
{ "permissions": { "deny": ["Write", "Edit", "NotebookEdit", "Bash", "PowerShell"] } }
exit=0
exists=False
type : result
...
이 경우에는 permission_denials가 비어있었습니다(0건). deny로 금지한 도구는 처음부터 사용할 수 없는 취급을 받기 때문에, '호출해서 거부되었다'는 기록이 남지 않는 것으로 추정됩니다.
permission_denials만 보고 판단하는 것만으로는 놓칠 수 있습니다. 참고로, deny를 ["Write"]만으로 설정하고 동일한 작업(acceptEdits)을 시도했을 때는 Bash와 PowerShell 호출이 거부된 후 최종적으로 hello.txt가 만들어졌습니다. '쓰기를 금지한다고 해서 쓰여지지 않는 것은 아니다'라는 점도 함께 주의해야 합니다.
[Console]::OutputEncoding = [Text.UTF8Encoding]::new($false)
function Invoke-ClaudeChecked {
param([string]$Prompt, [string]$ExpectedFile)
...
ExitCode : 0
IsError : False
Subtype : success
...
핵심 포인트는 다음 3가지입니다.
- 종료 코드는 '실행 시작 또는 API 실패'를 파악하기 위해 확인합니다. 요청이 달성되었는지 여부는 알 수 없습니다.
permission_denials는 '거부된 작업(operation)'을 확인할 수 있지만, deny 규칙으로 처음부터 제외된 도구는 포함되지 않습니다. 최종적으로는 기대하는 결과물(파일 또는 출력 내용)이 존재하는지를 확인해야 합니다.
[Console]::OutputEncoding을 UTF-8로 설정하지 않으면 Windows PowerShell 5.1 환경에서 JSON의 한글이 깨져서 ConvertFrom-Json 실행에 실패하는 경우가 있었습니다.
Claude Code의 deny 규칙으로 .env 파일을 읽지 못하게 하는 설정을 시도한 기록은 Zenn에 있습니다: https://zenn.dev/chukidx_dev/articles/claude-code-deny-env-windows
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기