0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude Code の claude -p は、書き込みを断られても終了コード 0 で終わる — スクリプトからは出力とファイルで判定する

0
Posted at

結論

Claude Code(Anthropic のターミナルで動く AI コーディングエージェント)を claude -p(非対話モード)でスクリプトから呼ぶと、ファイルの書き込みが権限の確認や設定で断られても、終了コードは 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 確認)

権限で断られるのは「実行の失敗」ではなく「依頼の一部ができなかった」扱いなので、終了コードには出ない、という整理になります。

再現手順

空の一時フォルダで、ファイルを1つ作るよう頼みます。私は Claude Code の画面の中から試したため、親セッションの環境変数(CLAUDE で始まるもの)を消した新しい PowerShell で実行しました。

Set-Location <TEMP>\case
[Console]::OutputEncoding = [Text.UTF8Encoding]::new($false)   # claude の UTF-8 出力を正しく受け取る
$out = claude -p 'このフォルダに hello.txt というファイルを作り、中身を hi の1行にしてください。' --output-format text 2>$null
"exit=$LASTEXITCODE"
"exists=" + (Test-Path .\hello.txt)
$out

結果1: 何も指定しない(Manual モード)

exit=0
exists=False
hello.txt はまだ作れていません。このフォルダへの書き込みを許可していただけなかったので、ファイルは作成されていません。

作るのであれば、書き込みを許可したうえでもう一度お知らせください。中身が `hi` の1行だけの hello.txt を作ります。

返答の文面は実行ごとに少し変わりますが、この条件(モード指定なし)で5回試して、5回とも終了コード 0・ファイルなしでした。

--output-format json にすると、断られた操作が permission_denials に入ります(抜粋)。

{
  "type": "result",
  "subtype": "success",
  "is_error": false,
  "num_turns": 2,
  "permission_denials": [
    { "tool_name": "Write",
      "tool_input": { "file_path": "<TEMP>\\case\\hello.txt", "content": "hi\n" } }
  ]
}

結果2: 設定で書き込み系のツールを禁止する

.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
subtype   : success
is_error  : False
num_turns : 2
result    : hello.txt は作れていません。このセッションにはローカルにファイルを書き込めるツール(Write や Bash)が無く、…

このときは permission_denials が空(0件) でした。deny で禁止したツールは最初から使えない扱いになり、「呼んで断られた」記録が残らないためと考えられます。permission_denials だけを見る判定でも見逃します。

なお、deny を ["Write"] だけにして同じこと(acceptEdits)を試すと、Bash と PowerShell の呼び出しが断られたあと、最終的に hello.txt は作られました。「Write を禁止すれば書き込まれない」わけではない点も、合わせて注意が必要です。

対処: 終了コード・JSON・成果物の3つで判定する

[Console]::OutputEncoding = [Text.UTF8Encoding]::new($false)

function Invoke-ClaudeChecked {
    param([string]$Prompt, [string]$ExpectedFile)
    $raw  = & claude -p $Prompt --output-format json 2>$null
    $code = $LASTEXITCODE
    $r    = ($raw -join "`n") | ConvertFrom-Json
    $denied = @($r.permission_denials).Count
    $exists = Test-Path -LiteralPath $ExpectedFile
    [pscustomobject]@{
        ExitCode = $code
        IsError  = $r.is_error
        Subtype  = $r.subtype
        Denials  = $denied
        Exists   = $exists
        OK       = ($code -eq 0) -and (-not $r.is_error) -and ($denied -eq 0) -and $exists
    }
}

$res = Invoke-ClaudeChecked -Prompt 'このフォルダに hello.txt というファイルを作り、中身を hi の1行にしてください。' -ExpectedFile (Join-Path $PWD 'hello.txt')
$res | Format-List
if (-not $res.OK) { Write-Output '失敗として扱います' }
ExitCode : 0
IsError  : False
Subtype  : success
Denials  : 1
Exists   : False
OK       : False

失敗として扱います

ポイントは次の3つです。

  • 終了コードは「起動や API の失敗」を拾うために見る。依頼が達成できたかは分からない
  • permission_denials は「断られた操作」を拾えるが、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

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?