Claude CLI cron jobs no longer regress to interactive mode
Custom Claude CLI arguments now preserve the non-interactive permission mode that background jobs depend on, preventing silent failures in cron and heartbeat runs.
Cron and heartbeat jobs that rely on the Claude CLI were failing silently when users configured custom arguments. Any args array that didn't include a permission flag—say, adding --verbose or changing --output-format—would drop the special --permission-mode bypassPermissions flag required for non-interactive execution. The result was a cryptic "exec denied" error, with no indication that the permission mode was the culprit.
The fix is straightforward: instead of only injecting bypassPermissions when the legacy skip-permissions flag was present, the system now always injects it whenever no explicit permission mode exists. Custom args that specify a different mode, like acceptEdits, are respected. The change lives in the Claude CLI extension, affecting any agent run triggered by automated scheduling.
View Original GitHub Description
Summary
- When users customize
cliBackends.claude-cli.args(e.g. adding--verboseor changing--output-format), the user's array completely replaces the default args viamergeBackendConfig(). This drops--permission-mode bypassPermissionsfrom the resolved config. normalizeClaudePermissionArgs()inextensions/anthropic/cli-shared.tsonly re-injectedbypassPermissionswhen the legacy--dangerously-skip-permissionsflag was present. If neither permission flag existed in the custom args, it did nothing.- This causes all cron/heartbeat runs to silently fail with
"exec denied: Cron runs cannot wait for interactive exec approval"because the CLI subprocess launches in default interactive permission mode.
Fix: Always inject --permission-mode bypassPermissions when no explicit --permission-mode flag is found in the resolved args. Users who explicitly set a different permission mode (e.g. acceptEdits) are unaffected.
Reproduction
- Configure custom
cliBackends.claude-cli.argsinopenclaw.json:"args": ["-p", "--output-format", "stream-json", "--verbose"] - Set up a cron job that triggers an agent using
claude-cli/*models - The cron run fails with:
exec denied: Cron runs cannot wait for interactive exec approval
Test plan
- Existing tests pass (no regressions on default args, legacy normalization, explicit overrides)
- New test: custom args without any permission flag ->
bypassPermissionsis injected - Manual: verify cron heartbeats succeed after applying this fix
Rebased onto current main. Supersedes #61109.