◉CLAUDE LABJP
●CODE 2.1.319 — Claude Code now moves MCP tasks to the background automatically, and a denyInsteadOfPrompting setting denies calls that would wait on a prompt●CONSOLE — Console IP allowlist is in beta (11/5): requests from addresses not on the list are refused●SONNET 4.5 — Retires on the Claude API on 11/30, 23 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST — Opus 4.8 fast mode is deprecated and will be removed on 11/30. Migrate to Opus 5.5●NEW — I Put a Ten-Line Promise File at the To…●CODE 2.1.319 — Claude Code now moves MCP tasks to the background automatically, and a denyInsteadOfPrompting setting denies calls that would wait on a prompt●CONSOLE — Console IP allowlist is in beta (11/5): requests from addresses not on the list are refused●SONNET 4.5 — Retires on the Claude API on 11/30, 23 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST — Opus 4.8 fast mode is deprecated and will be removed on 11/30. Migrate to Opus 5.5●NEW — I Put a Ten-Line Promise File at the To…
Articles/Claude Code
⟐ Claude Code/2026-11-08Intermediate

Before a Nightly Job Hangs on a Prompt: Designing Around denyInsteadOfPrompting

Claude Code 2.1.319 adds permissions.denyInsteadOfPrompting. Here is how it compares with other ways to answer permission prompts unattended, and how to catch what a denial quietly drops.

Claude Code283permissions15unattended5automation110design6

I have opened the log of an overnight job more than once to find the last line reading "waiting for confirmation." A person sitting next to it would have pressed Enter. Nobody was there, so it waited for hours.

The 2.1.319 changelog lists one new line aimed at exactly this wait: permissions.denyInsteadOfPrompting. This post is a design note written after reading that line and asking where I would use it. It is not a record of a verified run on my nightly jobs. Everything below rests on what the changelog says, and I'd rather tell you that up front.

What the changelog says (checked on November 8, 2026)

The primary source is a single line in 2.1.319.

ItemWhat is written
Settingpermissions.denyInsteadOfPrompting
EffectA tool call that would wait on a permission prompt is denied, and the turn continues
ScopeTerminal sessions, subagents and teammates
Not statedThe value type, the message the model receives on denial, any effect on exit codes

When I fetched the settings reference, I could not find an entry for it. I read the value as a boolean, but I won't claim more than that. Please confirm the type in the documentation for your own version before relying on it.

The same release has a neighboring change. In auto mode, when a safety check can't be obtained and the action is refused, claude -p now exits with code 1 for both text and JSON output. That reports "no check was available" through the exit code, and it is a different mechanism from this setting. Keeping the two apart makes it easier to find the cause later.

Three ways to answer a prompt without a person

I sort the options into three.

ApproachWho answersWhat a stop looks likeFits
Add allow rules up frontRules you wrote ahead of timeNo prompt appears at allFixed work whose scope you can state
Delegate to permission-prompt-toolYour own decision toolA ledger kept by that toolWork where you want every decision recorded, or inputs rewritten
Deny with denyInsteadOfPromptingNobody; the call is refused and the run goes onA failed tool call, then the turn continuesWork where unexpected actions may simply be declined

The third option costs almost nothing. You build no decision tool and enumerate no rules. One setting removes the worst outcome, a job frozen until morning.

What changes is how failure looks. A prompt wait is a loud stop. A denial lets the job finish, with exit code 0 and everything, while the deliverable you wanted is missing. It no longer freezes. It quietly comes up short.

For cases where an allow rule seems ignored, I wrote up how to read six layers in /permissions. For compound commands that keep asking, see the cd and git prompt that repeats. My order is to exhaust the "don't ask at all" side first, then send whatever remains to denial.

Decide success by the deliverable

Denials happen silently, so I decided not to hand the success check to exit codes or log wording. The only question is whether the file the job should produce exists, with content in it.

The settings I have in mind look like this.

{
  "permissions": {
    "allow": ["Read", "Write(reports/**)"],
    "denyInsteadOfPrompting": true
  }
}

Anything in allow goes through, and anything that would need a confirmation is refused without waiting. The launching script then inspects the output.

#!/usr/bin/env bash
# nightly-check.sh: decide success by the deliverable, even when denials let the run continue
set -u
OUT="reports/$(date +%F).md"
rm -f "$OUT"
 
claude -p "Write the delivery-data check results to ${OUT}" \
  --allowedTools "Read" "Write(reports/**)" >/tmp/nightly.log 2>&1
CODE=$?
 
if [ ! -s "$OUT" ]; then
  echo "No deliverable: ${OUT} (claude exit code=${CODE})" >&2
  exit 2
fi
exit 0

I delete the file first so a stale report can't pass for a fresh one, and -s rejects an empty file. Because the changelog doesn't document the denial message, I'd avoid grepping for its wording. That would likely break whenever the version changes.

Where I draw the line

I only let a job fall back to denial when being declined wouldn't hurt me the next morning.

Checking the delivery data of a wallpaper app and writing a report is that kind of job. If an unexpected write is refused, nothing is lost, and a missing report is caught by the script above. Work that deletes data or sends something outside can end half-finished if it simply moves on after a denial. I keep those on allow rules that state the scope, or on a decision tool that records each call.

Not freezing is not the same as succeeding. If you turn on denial, put the success check on the deliverable.

One next step

Open the log of your most recent overnight run and look for a single place where it stopped on a confirmation. If it's an operation you can describe precisely, add it to allow. If it's something you're fine having declined, that is your candidate for denial. I'd write the script that inspects the deliverable before touching the setting.

Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

⟐ Claude Code2026-08-27
Trusting the allow rules in your repo, or moving them to the environment
On disposable machines, the permissions.allow rules committed to your repo are dropped while the workspace waits to be trusted. Here is what gets dropped and what survives on 2.1.246, where each kind of rule belongs, and a preflight that catches the gap before a run starts.
⟐ Claude Code2026-07-27
Whose Environment Expands That Variable? Fingerprinting Your Effective Managed MCP Policy
Variable references in the Managed MCP allowlist and denylist now resolve from the startup environment and the managed-settings env block. I rebuilt both resolution orders locally to see where verdicts diverge, then wrote a preflight check that reduces the effective policy to a comparable fingerprint.
⟐ Claude Code2026-10-24
The Settings File I Kept Saying Yes To Had a Rule That Let Any Python Through — Auditing Allow Rules After the 2.1.309 Changelog
Claude Code 2.1.309 is full of permission-check and sandbox fixes. Here is a script that audits the allow rules in settings.local.json, and how to fix a prefix wildcard on an interpreter.