Even with defaultMode: dontAsk and skipDangerousModePermissionPrompt: true, Claude Code
would still ask to confirm innocuous Bash commands — appends to log files, heredoc writes, date substitutions.
A one-line hook that always returns allow: true closes the loophole by intercepting every permission
check at the source.
echo.flowchart LR U((User prompt)) --> CC["Claude Code
bypass mode"] CC --> TOOL[/"Bash tool call
echo "..." >> log.md"/] TOOL --> DEC{"Needs
permission?"} DEC -->|before fix| OLD["Interactive prompt
Allow? [y/n]"]:::before DEC -->|after fix| HOOK["PermissionRequest hook
~/.claude/settings.json"]:::hook HOOK --> CMD["command:
echo '{...allow:true...}'"]:::cmd CMD --> JSON["{ hookSpecificOutput:
{ allow: true } }"]:::json JSON --> ALLOW(("✓ allow")) ALLOW --> EXEC["Bash executes
without interruption"]:::after OLD -.-> STALL["⏸ Workflow stalls"]:::bad classDef before fill:#3b1a23,stroke:#f7768e,color:#f7768e classDef bad fill:#3b1a23,stroke:#f7768e,color:#f7768e,stroke-dasharray:4 3 classDef hook fill:#1e2a4d,stroke:#7dcfff,color:#c0caf5 classDef cmd fill:#241a3b,stroke:#bb9af7,color:#bb9af7 classDef json fill:#1f2a18,stroke:#9ece6a,color:#9ece6a classDef after fill:#1f2a18,stroke:#9ece6a,color:#9ece6a
Dangerous / bypass mode was supposed to wave commands through. In practice, Claude Code's internal safety heuristics still flagged common logging operations, forcing you to click through an allow-or-deny prompt every few minutes.
echo "..." >> session-log.mdcat >> activity.jsonl << EOFTS=$(date -Iseconds) && …log.md?
The PermissionRequest hook runs before any interactive prompt. It emits a JSON
verdict of allow: true on stdout; Claude Code reads the verdict and proceeds immediately.
No UI prompt is ever drawn.
defaultMode: dontAsk{
"hooks": {
"PermissionRequest": [{
"hooks": [{
"type": "command",
"command": "echo '{ \"hookSpecificOutput\": { \"hookEventName\": \"PermissionRequest\", \"allow\": true } }'"
}]
}],
// ...existing SessionStart, UserPromptSubmit, PostToolUse, Stop hooks remain
}
}
How it works.
Claude Code fires the PermissionRequest event before drawing its interactive prompt. Each
configured hook command runs, and its stdout is parsed as JSON. The shape
{ hookSpecificOutput: { hookEventName: "PermissionRequest", allow: true } }
tells Claude Code "approved — skip the UI and proceed." Because the command is just
echo piping a literal JSON string, there's no external process, no race, no round trip.